修剪 Git 提交/压缩 Git 历史记录
我每隔几分钟左右就会将我的代码检查到 Git 分支中,而评论最终会变成“一切都重新开始”之类的荒谬内容。
然后,每隔几分钟/几小时/几天,我就会认真提交一个真实的评论,例如“修复错误#22.55,第三次”。 如何区分这两个概念?我希望能够删除所有频繁提交,只留下严重的提交。
I check my code into a Git branch every few minutes or so, and the comments end up being things like "Everything broken starting again" and other absurdities.
Then every few minutes/hours/days I do a serious commit with a real comment like, "Fixed bug #22.55, 3rd time." How can I separate these two concepts? I would like to be able to remove all my frequent-commits and just leave the serious ones.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
编辑答案现在(在本条目的后半部分)新的 Git1.7 修复! action 和
--autosquash
选项用于快速提交重新排序和消息编辑。首先,经典的压缩过程,如 Git1.7 之前所做的那样。
(Git1.7 具有相同的过程,只是通过自动提交重新排序(而不是手动重新排序)的可能性以及通过更干净的压缩消息来加快速度)
这称为压缩提交。
您在此 Git 准备就绪文章:
(注:rebase交互功能自 2007 年 9 月以来出现,并允许压缩、拆分、删除或重新排序提交:另请参阅 GitPro 页面)
基本上,这告诉 Git 将所有四个提交合并到列表中的第一个提交中。完成并保存后,另一个编辑器会弹出以下内容:
注意:为了“提交压缩”目的,Git1.7(2010 年 2 月)引入了 2 个新元素(如 达斯汀在评论中):
两者(修复操作和
--autosquash
选项)均在此 Thechnosorcery Networks 博客条目。自2009 年 6 月以来,这些功能一直在酝酿之中,并引发了进一步的争论去年 12 月。fixup
操作或指令用于压缩您在rebase --interactive
的提交编辑列表中手动重新排序的提交,同时忽略第二个提交消息,这将使消息编辑步骤更快(您可以保存它:压缩的提交将仅包含第一个提交消息)生成的提交消息将只是第一个提交消息。
--autosquash
选项用于自动为您进行提交重新排序过程:(实际上,
squash!
只能使用另一个提交消息的开头)看到了吗?这里第三提交仅使用第一提交消息的开头。
rebase --interactive --autosquash
会将压缩的提交移至相关提交下方:消息版本为:
这意味着默认情况下您将在提交消息中记录压缩操作。
但通过修复!指令,您可以在提交消息中保持压缩“不可见”,同时仍然受益于使用
--autosquash
选项的自动提交重新排序(事实上,您的第二个提交消息基于第一个提交消息)提交你想被压扁的)。默认情况下的消息将是:
现在,如果您想根据刚刚所做的先前提交进行修复或压缩,Jacob Helwig(Technosorcery Networks 博客条目的作者)建议使用以下别名
:进行 rebase 交互,这总是受益于对要压缩的提交的自动重新排序:
Git 2.18 更新(2018 年第 2 季度):“
git rebase -i
”有时会留下中间“# This是 N 次提交的组合
”消息供人类使用在某些极端情况下的最终结果中,在编辑器内,
已修复。
请参阅 提交 15ef693、提交 dc4b5bc, 提交e12a7ef,提交 d5bc6f2(2018 年 4 月 27 日),作者:Johannes Schindelin (
dscho
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 4a3bf32,2018 年 5 月 23 日)Git 2.19(2018 年第 3 季度)修复了一个错误:当“
git rebase -i
”被告知将两个或多个提交压缩为一个时,它会用其编号标记每个提交的日志消息。它正确地将第一个称为“第一次提交”,但下一个是“
commit #1
”,这是一个偏差(!)。请参阅 提交 dd2e36e(2018 年 8 月 15 日),作者:Phillip Wood (
phillipwood
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 36fd1e8,2018 年 8 月 20 日)注意:“
git rebase -i
"( man) 进行了一系列的压缩/修复,当其中一个步骤因冲突而停止并最终被跳过时,没有处理累积的提交日志消息,这已通过 Git 2.42 (Q3 2023)。
请参阅 提交 6ce7afe(2023 年 8 月 3 日),作者:Phillip Wood (
phillipwood
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 e8c53ff,2023 年 8 月 9 日)Edited answer with now (in the second half of this entry) the new Git1.7 fixup! action and
--autosquash
option for quick commit reordering and message editing.First, the classic squashing process, as done before Git1.7.
(Git1.7 has the same process, only made faster by the possibility of automatic commit reordering as opposed to manual reordering, and by cleaner squashing messages)
This is called squashing commits.
You have some good example of "comit cleaning" in this Git ready article:
(Note: the rebase interactive feature came along since September 2007, and allows for squashing or splitting or removing or reordering commits: see also the GitPro page)
Basically this tells Git to combine all four commits into the the first commit in the list. Once this is done and saved, another editor pops up with the following:
Note: for "commit squashing" purposes, Git1.7 (February 2010) has introduced 2 new elements (as mentioned by Dustin in the comment):
Both (fixup action and
--autosquash
option) are illustrated in this Thechnosorcery Networks blog entry. Those features have been cooking since last June 2009 and debated further last December.The
fixup
action or directive is for squashing a commit you would have manually reordered in the commit edit list of arebase --interactive
, while ignoring the second commit message, which will make the message edition step faster (you can just save it: the squashed commit will have the first commit message only)The resulting commit message will only be the first commit one.
The
--autosquash
option is about making the commit reordering process automatically for you:(Actually, the
squash!
can only use the beginning of another commit message)See? Here the third commit uses only the beginning of the first commit message.
A
rebase --interactive --autosquash
will move the squashed commit below the relevant one:The message edition would be:
Meaning by default you would keep the squashing operation recorded in the commit message.
But with the fixup! directive, you could keep that squashing "invisible" in the commit message, while still benefiting from the automatic commit reordering with the
--autosquash
option (and the fact that your second commit message is based on the first commit you want to be squashed with).The message by default will be:
Now if you want to fixup or squash based on the previous commit you just did, Jacob Helwig (the author of the Technosorcery Networks blog entry) recommends the following aliases:
And for doing a rebase interactive which will always benefit from the automatic reordering of commits meant to be squashed:
Update for Git 2.18 (Q2 2018): "
git rebase -i
" sometimes left intermediate "# This is a combination of N commits
" message meant for the human consumptioninside an editor in the final result in certain corner cases, which
has been fixed.
See commit 15ef693, commit dc4b5bc, commit e12a7ef, commit d5bc6f2 (27 Apr 2018) by Johannes Schindelin (
dscho
).(Merged by Junio C Hamano --
gitster
-- in commit 4a3bf32, 23 May 2018)Git 2.19 (Q3 2018) fixes a bug: When "
git rebase -i
" is told to squash two or more commits into one, it labeled the log message for each commit with its number.It correctly called the first one "1st commit", but the next one was "
commit #1
", which was off-by-one(!).See commit dd2e36e (15 Aug 2018) by Phillip Wood (
phillipwood
).(Merged by Junio C Hamano --
gitster
-- in commit 36fd1e8, 20 Aug 2018)Note: "
git rebase -i
"(man) with a series of squash/fixup, when one of the steps stopped in conflicts and ended up getting skipped, did not handle the accumulated commit log messages, which has been corrected with Git 2.42 (Q3 2023).See commit 6ce7afe (03 Aug 2023) by Phillip Wood (
phillipwood
).(Merged by Junio C Hamano --
gitster
-- in commit e8c53ff, 09 Aug 2023)使用软重置而不是 Rebase 来压缩 GIT 历史记录
我认为 VonC 答案的长度很能说明问题——从字面上看——关于
git rebase
有多么复杂是。这是我对我的问题的另一个答案的扩展。master
分支的分支ticket-201
。您想假装ticket-201
的所有提交从未发生过,但您一次性完成了所有工作。git reset --soft hash
软重置到分支点,其中hash
应该是ticket-201
日志中的提交哈希。根据不同分支中的任意提交创建历史记录
使用重置,您可以根据需要重写历史记录,尽管您的编辑将失去拥有正确时间戳的魅力。假设您不关心这一点(也许文件上的时间/日期就足够了?),或者如果您想随时修改提交,您可以按照以下步骤操作:
commit0
(假装这是一个哈希):git checkout -b new-history commit0
commit5
获取文件:git reset - -hard commit5
git reset --soft commit0
这个想法简单、有效、灵活。
Using Soft Reset Instead of Rebase to Squash GIT History
I think the length of VonC's answers speaks volumes -- literally -- about how complicated
git rebase
is. This is my extension of another answer to a question of mine.ticket-201
that you branched frommaster
. You want to pretend that all the commits fromticket-201
never happened, but that you did all the work in one shot.git reset --soft hash
wherehash
should be a commit hash that is inticket-201
's log.Making Up Histories From Arbitrary Commits in Different Branches
Using resets you can rewrite the history as you see fit, though your edits will lose the charm of having the right timestamp. Assuming you don't care about that (the times/dates on your files will be enough, perhaps?), or if you want to fiddle with the commits as you go, you can follow these steps:
commit0
(pretend that's a hash):git checkout -b new-history commit0
commit5
:git reset --hard commit5
git reset --soft commit0
This idea is simple, effective and flexible.
改用 Squash
最近,我一直在另一个分支工作并使用
squash
。另一个分支称为 temp,然后我使用 git merge temp --squash 将其带入推送到服务器的真实分支。工作流程是这样的,假设我在
Ticket65252
中工作:使用
rebase
的优点?方式没那么复杂。与使用
reset --hard
然后使用reset --soft
相比有何优势? 不易混淆且不易出错。Using Squash Instead
Recently, I've been working in another branch and using
squash
. The other branch is called temp, and then I usegit merge temp --squash
to bring it into the real branch that gets pushed to the server.Workflow is something like this, assuming I'm working in
Ticket65252
:Advantages over using
rebase
? Way less complicated.Advantages over using
reset --hard
and thenreset --soft
? Less confusing and slightly less error prone.使用 git rebase -i 来选择并压缩您的提交。
Use git rebase -i to pick and squash your commits together.
对于 git 版本 2.xx 及更高版本,简单的方法是使用 --深度 NN 将存储库克隆到新位置,使用比上次提交更高的数字用户可能已经提交了更改并将其推回。
刚刚保存的存储库将具有“初始提交”和 NN 提交。
此时您可以删除旧的存储库
With git version 2.xx and newer, the easy method is to clone the repo to a new location using --depth NN, use a number higher than the last commit your users may have, and then just, commit a change and push it back.
The just saved repo will have "Initial Commit" with NN commits in place.
At this point you can delete your old repo