如何压缩合并的 git 变更集

How to squash merged git changeset

是否可以在 Git 历史中删除像 #9701282 这样的提交?
我不是说 #b372fa5 以上的回购应该改变,
只是图表应该在这个地方进行简化。
提交紫色分支看起来是多余的。
#b372fa5 合并点内应用它的更改应该不是很难。
实施此操作有哪些技术?

git branch -d branch_name

删除合并的分支(别担心,如果没有合并,它不会删除任何东西,为此你需要 git branch -D)

要查看所有当前合并的分支,请尝试:

git branch --merged

如果你想让你的历史保持线性,我建议使用 git rebase

总的来说,保留您的历史记录有时是个好主意。

像往常一样,我会推荐https://git-scm.com/book/en/v2第3章。它真的会帮助你更好地理解一切。

如果您真的想要删除 提交(删除分支只会使它们无法访问,那么我建议阅读有关 reflogs 的内容 - 不过要小心, git 中很少有东西可以破坏你的 repo 并永久删除你的代码,但这可能只是其中之一)

Git就像老科幻电影里的经典时光机。你可以回到过去,但如果你改变了过去,你就会影响现在。

您可以使用 git 最强大的功能之一 rebase 做任何您想做的事情,但是,修改后的对象名称(包括修改后的提交)将被更改。

如果您正在与他人合作,建议不要这样做,因为他们必须从手术中恢复过来。

这里有一个前后对比的例子我只是运行作为例子:

git log --oneline --graph
* d3959f3 Something
* 9e58b42 Modify new
*   ad1dea6 Merge branch 'mybranch'
|\  
| * e75658b somechange
* | 1076214 New File
* | 49fe418 Updated on master
|/  
* b94640d Updated
* da15c9c Initial commit

git log --oneline --graph
* 89fe296 Something
* d9620cc Modify new
* 6301614 New File - somechange
* 49fe418 Updated on master
* b94640d Updated
* da15c9c Initial commit

执行我使用的操作:

git rebase -i ad1dea6~2

# a more common form is to modify n number of commits starting at HEAD
git rebase -i HEAD~n

这将打开已配置的编辑器,其中包含您在 "todo list" 中指定的更改,允许您以交互方式选择、压缩、重写、删除、重新排序,甚至 运行 任意 shell 命令执行

这是它在 vi 中的样子:

pick 1076214 New File
pick e75658b somechange
pick 9e58b42 Modify new
pick d3959f3 Something

# Rebase 49fe418..d3959f3 onto 49fe418
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

我选择了最简单的选项来压缩更改,它甚至不需要解决冲突,但会提示您确认提交消息(如您​​所见,我确实进行了更改)。

一旦我保存了提交消息更改 git 自动重写了其余的历史记录而没有进一步提示我。

我什至可以通过使用 git 方便的 reflog 命令来尝试一些不同的排列。

git reflog

在 git 中,即使是孤立的更改也可以恢复,只要它们没有在 gc 运行 中收集。您可以随时使用 gc 调用垃圾收集器,但有些命令会定期执行此操作。

reflog 的不良状态中恢复的一种方法是在 reflog 中找到您有兴趣返回的点和 运行:

git reset --hard <SHA>

在工作流中使用变基

之前的讨论集中在使用 rebase 来改变 rebase -i 的历史。这对于本地工作流程来说实际上是一个非常有用的功能,您希望在处理功能时定期提交,然后在与其他人合并到协作 b运行ch 之前,您可以重新组织本地提交以使历史更容易读取或合并提交以在每次提交时创建工作代码。

第二个用例是执行 rebase 合并。这可以通过将 merge 的用法替换为 rebase.

来完成
git rebase master

描述其工作原理的最佳方式是想象当前 b运行ch 上的所有更改都被存储起来,让您处于两个 b运行ch 的共同提交中分歧。接下来 b运行ch 被“快进”到目标 b运行ch 上的最新提交。最后,存储的提交在新的 HEAD 之上一个接一个地应用,让您有机会在每次提交时解决冲突(与合并相反,您只在形成合并提交时才解决冲突)。结果是一组全新的提交(新的时间戳和所有,可能通过冲突解决更改进行了修改)给出了外观运行ce,这些更改是在目标 b运行ch HEAD 之后按顺序进行的.

您还可以将 --rebase 选项与 pull 一起使用。

注意: 一些工作场所不喜欢更改提交历史,甚至更喜欢在执行合并时使用 --no-ff 禁用快进合并。何时使用变基以及它是否适合您的情况显然取决于您的判断。您通常仍然可以使用本地交互表单来自定义您自己的工作流程,因为这些更改尚未推送到远程。

其中一些内容来自我最近 blog post 的一般 git 用法。我试图包含更多的平均信息,同时尽可能保持紧凑。

如果整个提交树都是正确的,如果只需要更改 parent,那么使用 graftgit filter-branch 就很容易做到。

首先,假设 b372fa5^b372fa5 的唯一 parent。

echo $(git rev-parse b372fa5 b372fa5^) > .git/info/grafts

然后查看历史记录是否正确:

git log --graph

然后重写提交以使这个嫁接永久化:

git filter-branch

最后清理:

rm .git/info/grafts