在Git中,有没有办法将所有更改从一个分支合并到另一个分支,但是同时压缩到一个提交?
我经常在一个单独的分支中处理一个新功能,并且会定期提交/推送 - 主要用于备份或将我正在处理的内容转移到另一台机器上。大多数提交说“功能xxx WIP”或多余的东西。
一旦完成这项工作并且我想将WIP分支合并回master,我想放弃所有这些中间提交,只需要一次干净的提交。
有一种简单的方法吗?
或者,如果一个命令压缩了分支上的所有提交,那么它是如何分支的?
答案 0 :(得分:519)
另一个选项是git merge --squash <feature branch>
,然后最后执行git commit
。
--squash
--no-squash
生成工作树和索引状态,就像真正合并一样 发生了(合并除外) 信息),但实际上并没有 提交或移动
HEAD
,也不记录$GIT_DIR/MERGE_HEAD
导致下一个git commit
命令用于创建合并 承诺。这允许您创建一个 在当前的单一提交 分支的效果与 合并另一个分支(或更多) 章鱼的情况。)
答案 1 :(得分:198)
--squash
选项
git checkout master
git merge --squash WIP
此时所有内容都已合并,可能存在冲突,但未提交。所以我现在可以:
git add .
git commit -m "Merged WIP"
答案 2 :(得分:23)
在功能分支上尝试git rebase -i master
。然后,你可以将除了一个'pick'之外的所有内容更改为'squash'来组合提交。见squashing commits with rebase
最后,您可以从主分支进行合并。
答案 3 :(得分:6)
使用git merge --squash <feature branch>
作为accepted answer可以达到目的,但不会显示合并的分支实际上是合并的。
因此,更好的解决方案是:
<feature branch>
将git merge --squash
合并到上面This wiki详细说明了该过程。
答案 4 :(得分:2)
使用--squash
标志,它看起来像两个没有关系的平行分支:
与日期相关的排序提交如下:
我个人不喜欢--squash选项,请尝试此技巧,也许它符合您的需求,我将其用于小型项目:
空提交有意合并冲突,将其命名为您喜欢的任何内容
答案 5 :(得分:0)
我已经创建了自己的git别名来做到这一点。我叫git freebase
!它将使用您现有的混乱,无法修复的功能分支并重新创建它,以使其成为具有相同名称的新分支,其提交被压缩为一次提交并重新基于您指定的分支(默认为master)。最后,它将允许您将喜欢的任何提交消息用于新的“基于Freefree”的分支。
通过在.gitconfig中放置以下别名来安装它:
[alias]
freebase = "!f() { \
TOPIC="$(git branch | grep '\\*' | cut -d ' ' -f2)"; \
NEWBASE="${1:-master}"; \
PREVSHA1="$(git rev-parse HEAD)"; \
echo "Freebaseing $TOPIC onto $NEWBASE, previous sha1 was $PREVSHA1"; \
echo "---"; \
git reset --hard "$NEWBASE"; \
git merge --squash "$PREVSHA1"; \
git commit; \
}; f"
通过运行以下命令从功能分支中使用它:
git freebase <new-base>
我只测试了几次,所以请先阅读并确保您要运行它。作为一点安全措施,它确实会打印开始的sha1,因此,如果出现任何问题,您应该能够恢复旧分支。
我将在github上的dotfiles存储库中维护它: https://github.com/stevecrozz/dotfiles/blob/master/.gitconfig
答案 6 :(得分:-1)
git merge --squash <feature branch>
是一个不错的选择。“git commit”会告诉您所有功能分支提交消息,您可以选择保留它。
用于较少的提交合并。
git merge 做x次--git reset HEAD ^ --soft 然后git提交。
风险 - 删除的文件可能会回来。
答案 7 :(得分:-4)
我想把我主人的所有提交压缩成一个。我尝试了这个失败了:
$ git checkout --orphan new_master
$ git merge --squash master
fatal: Squash commit into empty head not supported yet
所以我这样做了:
$ tar cf /tmp/git.tar --exclude .git .
$ git checkout --orphan new_master
$ tar xf /tmp/git.tar
$ git commit -m "Initial commit"
效果很好。
答案 8 :(得分:-5)
您可以使用“rebase”命令执行此操作。我们将分支称为“主要”和“特征”:
git checkout feature
git rebase main
rebase命令会将“feature”上的所有提交重放为一个提交,其父级等于“main”。
如果“main”自“功能”创建以来(或自最近一次合并以来)发生了变化,您可能希望在git merge main
之前运行git rebase main
。这样,如果发生合并冲突,您仍然可以获得完整的历史记录。
在rebase之后,你可以将你的分支合并到main,这将导致快进合并:
git checkout main
git merge feature
请参阅rebase的Understanding Git Conceptually页面以获得良好的概述