合并(使用挤压)来自另一个分支的所有更改为一次提交

在Git中,是否有一种方法可以将所有变更从一个分支合并到另一个分支,同时压缩到单个提交中?

我经常在一个单独的分支中处理一个新特性,并定期提交/推送——主要是为了备份或将我正在做的工作转移到另一台机器上。大多数提交的内容都是“功能xxx WIP”或一些多余的内容。

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

有什么简单的方法吗?

或者,如果一个命令从分支所在的位置开始压缩分支上的所有提交呢?

238500 次浏览

您可以使用“rebase”命令来完成此操作。让我们称分支为“main”和“feature”:

git checkout feature
git rebase main

rebase命令将重播“feature”上的所有提交,作为父级等于“main”的一次提交。

如果“main”在“feature”创建之后(或者在最近的合并之后)发生了变化,你可能想在git rebase main之前运行git merge main。这样,您仍然拥有完整的历史记录,以防遇到合并冲突。

在rebase之后,你可以将你的分支合并到main,这应该会导致一个快进合并:

git checkout main
git merge feature

请参阅从概念上理解Git变基页以获得良好的概述

在你的特性分支上尝试git rebase -i master。然后,你可以将除一个“pick”以外的所有“pick”更改为“squash”,以合并提交。看到# EYZ1

最后,您可以从主分支进行合并。

发现它!合并命令有一个--squash选项

git checkout master
git merge --squash WIP

此时,所有内容都已合并,可能存在冲突,但尚未提交。所以我现在可以:

git add .
# git add -u  # might be preferable, see below
git commit -m "Merged WIP"

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

从# EYZ0

# EYZ0

# EYZ0

生成工作树和索引状态,就像真正的合并一样 发生了(除了合并 信息),但实际上并不制造 提交或移动HEAD,也不是记录 $GIT_DIR/MERGE_HEAD引起下一个 git commit命令创建一个合并 提交。这允许您创建一个 在当前的基础上进行单次提交 效果相同的分支 合并另一个分支(或更多分支)

git merge --squash <feature branch>是一个不错的选择。“git commit”告诉你所有的特性分支提交消息,你可以选择保留它。

为了减少提交合并。

< p > git合并 做x次——git重置头^——软 然后git提交。< / p >

风险删除的文件可能会回来。

我已经创建了自己的git别名来做到这一点。我叫它git freebase!它将使用您现有的凌乱的、不可重基的特性分支并重新创建它,以便它成为一个具有相同名称的新分支,其提交压缩到一个提交中,并重新基于您指定的分支(默认为master)。在最后,它将允许您为新“基于免费”的分支使用任何您喜欢的提交消息。

通过在.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"

使用它从你的特征分支通过运行: # EYZ0 < / p >

我只测试了几次,所以请先阅读它,并确保您想要运行它。作为一个小小的安全措施,它会打印开始的sha1,所以如果出现任何错误,你应该能够恢复旧的分支。

我将在github上的dotfiles repo中维护它: # EYZ0 < / p >

使用git merge --squash <feature branch>作为接受的答案的建议可以达到这个目的,但是它不会显示实际合并的分支。

因此,更好的解决方案是:

  • 最新的主创建一个新分支,在特性分支发起的主分支中提交。
  • 使用git merge --squash<feature branch>合并到上面
  • 将新创建的分支合并到master中。这样,特性分支将只包含一次提交,合并将在一个简短而整洁的插图中表示。

这个维基详细解释了这个过程。

在下面的例子中,左边的截图是qgit的结果,右边的截图是:

git log --graph --decorate --pretty=oneline --abbrev-commit

这两个屏幕截图显示同一存储库中相同的提交范围。尽管如此,由于--squash,右边的更紧凑。

  • 随着时间的推移,master分支偏离了db
  • db特性准备好后,在db具有根的master提交中创建了一个名为tag的新分支。
  • tag开始执行git merge --squash db,然后在一次提交中阶段性地提交所有更改。
  • mastertag合并到git merge tag
  • 分支search是不相关的,并且没有以任何方式合并。

enter image description here

2020年更新

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

enter image description here

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

enter image description here

就我个人而言,我不喜欢——挤压选项,试试这个技巧,也许它适合你的需求,我用它来做小项目:

  1. git init
  2. Git checkout -b dev
  3. 开发中的多次提交
  4. 当你在dev中做了一些很棒的提交后(但还没有合并到master分支),如果你不希望所有的提交都复制到master分支,那么故意改变master分支中的一些内容(在README文件中添加一些空行并在master分支中提交),
  5. git merge dev . 它导致合并冲突(README中的空行),解决它,提交您想要的新消息,然后就完成了。下面是它的可视化表示

Null提交故意合并冲突,命名为任何你喜欢

null commit for intended merge conflict .

你有一个主分支和一个特征分支。你在一个特性分支上有很多提交。你不希望特性分支的所有提交都出现在主节点的提交历史上。遵循以下步骤

  1. 从最新的主代码创建一个新分支,您就在那个分支中
git checkout -b latest_MCode
  1. 现在将你的feature分支合并到latest_Mcode分支中
git merge --squash feature
  1. 没有-m参数提交吗

Git提交#不带-m

编辑器应该是一个包含所有提交日志和从特性分支更改的文件的弹出窗口。你可以在这里看到所有的特性分支提交。如果你愿意,你可以删除所有内容,只写一行你想在合并到master后显示的提交消息。按“i”键,然后写下你的信息,然后按Esc->:wq->Enter键保存并退出编辑器。 4. 将新创建的分支合并到master

git checkout master
git merge latest_Mcode
git push
你完了! 原始答案可以在GithubLink

中找到