将来自另一个分支的所有更改合并为单个提交

时间:2010-09-12 23:52:41

标签: git

在Git中,有没有办法将所有更改从一个分支合并到另一个分支,但是同时压缩到一个提交?

我经常在一个单独的分支中处理一个新功能,并且会定期提交/推送 - 主要用于备份或将我正在处理的内容转移到另一台机器上。大多数提交说“功能xxx WIP”或多余的东西。

一旦完成这项工作并且我想将WIP分支合并回master,我想放弃所有这些中间提交,只需要一次干净的提交。

有一种简单的方法吗?

或者,如果一个命令压缩了分支上的所有提交,那么它是如何分支的?

9 个答案:

答案 0 :(得分:519)

另一个选项是git merge --squash <feature branch>,然后最后执行git commit

来自Git merge

  

--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合并到上面
  • 将新创建的分支合并到master中。这样,功能分支将仅包含一次提交,并且合并将以简洁明了的图示表示。

This wiki详细说明了该过程。

答案 4 :(得分:2)

2020更新

使用--squash标志,它看起来像两个没有关系的平行分支:

enter image description here

与日期相关的排序提交如下:

enter image description here

我个人不喜欢--squash选项,请尝试此技巧,也许它符合您的需求,我将其用于小型项目:

  1. git init
  2. git checkout -b dev
  3. 开发中有数次提交
  4. 在dev中进行了一些重大提交(但尚未合并到master)之后,如果您不希望将所有提交复制到master分支,则请有意地更改master中的某些内容,并在README文件中添加一些空行并提交在大师中),
  5. git merge开发 结果合并冲突(自述文件中的空行),解决了冲突,提交了您想要的新消息,然后您就完成了。这是它的视觉表示。

空提交有意合并冲突,将其命名为您喜欢的任何内容

null commit for intentionally merge conflict

答案 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

请参阅rebaseUnderstanding Git Conceptually页面以获得良好的概述