在推入 Git 之前合并多个提交 [重复]

Posted

技术标签:

【中文标题】在推入 Git 之前合并多个提交 [重复]【英文标题】:Combining multiple commits before pushing in Git [duplicate] 【发布时间】:2011-10-19 13:40:43 【问题描述】:

我的本​​地存储库中有一堆主题相似的提交。我想在推送到远程之前将它们组合成一个提交。我该怎么做?我认为 rebase 会这样做,但我无法理解文档。

【问题讨论】:

对于任意数量的提交进行变基/压缩,请参阅my answer to "Squash/combine/rebase an arbitrarily large number of commits"。 相关How can I squash my last X commits together using git?. “我无法理解文档”你并不孤单 一般来说,你应该三思而后行。更细粒度(更小)的提交有许多实际好处。如果需要对它们进行分组,您可以将它们全部放在一个单独的分支中,然后将该分支与 git merge --no-ff myOtherBranch 合并到主分支中。或者,您可以在提交消息中使用提交消息前缀或标签。 git history 不是公开的变更日志,而是开发人员使用的“内部”结构。 【参考方案1】:

您可能想使用Interactive Rebasing,该链接中有详细描述。

如果你搜索“git rebase interactive”,你可以找到其他好的资源。

【讨论】:

【参考方案2】:

您可以使用git rebase -i 执行此操作,传入您要用作“根”的修订:

git rebase -i origin/master

将打开一个编辑器窗口,显示您在origin/master 中的最后一次提交之后所做的所有提交。您可以拒绝提交、将提交压缩为单个提交或编辑以前的提交。

有一些资源可以更好地解释这一点,并展示一些其他示例:

http://book.git-scm.com/4_interactive_rebasing.html

http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html

是我能找到的前两个不错的页面。

【讨论】:

最后一个链接帮了大忙!它详细介绍了压缩提交的细节,让我很感谢,陌生人。【参考方案3】:

您想要做的事情在 git 中被称为“挤压”。执行此操作时有很多选项(太多?),但如果您只想将所有未推送的提交合并到一个提交中,请执行以下操作:

git rebase -i origin/master

这将打开您的文本编辑器(-i 用于“交互式”),文件如下所示:

pick 16b5fcc Code in, tests not passing
pick c964dea Getting closer
pick 06cf8ee Something changed
pick 396b4a3 Tests pass
pick 9be7fdb Better comments
pick 7dba9cb All done

将除第一个之外的所有pick 更改为squash(或s):

pick 16b5fcc Code in, tests not passing
squash c964dea Getting closer
squash 06cf8ee Something changed
squash 396b4a3 Tests pass
squash 9be7fdb Better comments
squash 7dba9cb All done

保存文件并退出编辑器。然后另一个文本编辑器将打开,让您将所有提交的提交消息合并成一个大提交消息。

瞧!谷歌搜索“git squashing”将为您提供所有其他可用选项的解释。

【讨论】:

origin/master,你的意思是<upstream-branch>吗?如果配置了上游分支,是隐式还是必须要指定? 使用fixup 而不是squash 跳过创建新提交消息的步骤。最后的提交消息(“All done”)将自动用于rebase 创建的最终提交。 @Jusleong 您只需删除该行即可从提交中删除更改。 任何人都知道您是否可以在“pick”行中包含多行提交消息,否则会混淆解析器吗? 好!你也可以使用 s 而不是 squash【参考方案4】:

如果您有 很多 次提交并且您只想压缩最后 X 次提交,请找到您要开始压缩的提交的提交 ID 并执行

git rebase -i <that_commit_id>

然后按照 leopd 的回答中的说明进行操作,将除第一个之外的所有 picks 更改为 squashes。

Example:

871adf OK, feature Z is fully implemented      --- newer commit --┐
0c3317 Whoops, not yet...                                         |
87871a I'm ready!                                                 |
643d0e Code cleanup                                               |-- Join these into one
afb581 Fix this and that                                          |
4e9baa Cool implementation                                        |
d94e78 Prepare the workbench for feature Z     -------------------┘
6394dc Feature Y                               --- older commit

你可以这样做(写下提交的数量):

git rebase --interactive HEAD~[7]

或者这个(写下你不想想要压缩的最后一次提交的哈希):

git rebase --interactive 6394dc

【讨论】:

我花了一些时间才弄清楚,但似乎 本身不会被压扁。 它应该说“在你想要压缩的一组提交之前找到提交的提交 ID”。 这有什么特别之处吗?我有一个 PR,它有 5 个提交 - 包括一个合并的合并冲突修复 - 如果我在 PR 日志中指定第一个提交的提交 ID,我只会在 rebase 选择/壁球列表中得到一些随机不相关的提交。跨度> 【参考方案5】:

我想出了

#!/bin/sh

message=`git log --format=%B origin..HEAD | sort | uniq | grep -v '^$'`
git reset --soft origin
git commit -m "$message"

合并、排序、统一和删除提交消息中的空行。我用它来对 github wiki 进行本地更改(使用 gollum)

【讨论】:

这确实是一个非常聪明的主意! 出于某种原因(可能是我的配置或我使用 GIT 的方式),origin..HEAD 给了我一个模棱两可的参数错误。为了确保它始终获取与当前分支头部的差异,我需要将带有 git log 的第一行改编为 git fetch &amp;&amp; git log --format=%B FETCH_HEAD..HEAD [...] 首先获取确保 GIT 拥有所需的最新知识并创建一个我们可以使用的 FETCH_HEAD 引用。【参考方案6】:

您可以使用 Interactive Rebase 压缩(加入)提交。有一个非常棒的 YouTube 视频展示了如何在命令行或使用 SmartGit 执行此操作:

https://www.youtube.com/watch?v=qi_QAFrmHJM

如果您已经是 SmartGit 用户,那么您可以选择所有传出提交(通过按住 Ctrl 键)并打开上下文菜单(右键单击)以压缩您的提交。

很舒服:

Atlassian 还提供了一个非常好的教程,展示了它是如何工作的:

https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase-i

【讨论】:

【参考方案7】:

而我的squashing 多个push 的方式是(也许您向自己的分支推送了许多提交,现在您希望进行拉取请求,并且您不想将它们与您已经拥有的许多提交混为一谈推)。我这样做的方式(据我所知,没有其他更简单的选择)。

    squash 创建新分支(您希望将请求拉到的原始分支的分支)。 推送新创建的分支。 将提交(已推送)的分支合并到新分支。 变基新分支并压缩。 推送新分支。 为现在具有单一提交的新分支创建新的拉取请求。

例子:

git checkout from_branch_you_wish_to_pull_request_to
git checkout -b new_branch_will_have_single_squashed_commit
git push -u new_branch_will_have_single_squashed_commit
git merge older_branch_with_all_those_multiple_commits
git rebase -i (here you squash)
git push origin new_branch_will_have_single_squashed_commit

您现在可以将请求拉入from_branch_you_wish_to_pull_request_to

【讨论】:

你也可以使用 mege --squash 来代替 merge + rebase。我最近将它用于完全相同的用例:从开发创建一个新分支,合并 --squash 功能分支并给它一个有意义的提交消息。 ***.com/a/5309051/4675841【参考方案8】:

这里有很多可行的答案,但我发现这是最简单的。此命令将打开一个编辑器,您可以在其中将 pick 替换为 squash 以便将它们删除/合并为一个

git rebase -i HEAD~4

其中,4 是您想要压缩为一个的提交数。这也解释了here。

【讨论】:

以上是关于在推入 Git 之前合并多个提交 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Git合并提交[重复]

Git将多个分支合并到一个新分支中[重复]

git - 回到某个提交 [重复]

git基础教程(26)git rebase -i合并多个提交

无效 BFG 使用后 Git 合并重复

签出旧提交并将其设为新提交 [重复]