修剪Git提交/压缩Git历史
我每隔几分钟检查我的代码到一个Git分支,最后的评论就是“一切都破了再开始”和其他荒谬的事情。
然后,每隔几分钟/几小时/天,我就会认真地提交一个真正的评论,例如“第三次修正了错误#22.55”。 我怎样才能分开这两个概念? 我希望能够删除所有我的频繁提交,只留下严重的提交。
现在编辑答案 (在本文的后半部分)新的Git1.7修复! 动作和 – --autosquash
选项快速提交重新sorting和消息编辑。
首先是经典的压缩过程,就像在Git1.7之前所做的那样。
(Git1.7具有相同的过程,只有通过自动提交重新sorting的可能性,而不是手动重新sorting,并通过更干净的挤压消息,速度更快)
我希望能够删除所有我的频繁签证,只留下严重的。
这被称为压制提交 。
在这个Git就绪的文章中,你有一个很好的例子:“清理”
(注意: 自2007年9月以来 ,rebase交互function一直在使用 ,并允许压缩或拆分或删除或重新sorting提交:请参阅GitPro页面 )
谨慎的说法:只对未被推送到外部存储库的提交执行此操作。 如果其他人已经根据您要删除的提交进行工作,则可能会发生很多冲突。 只要不与其他人共享,就不要重写历史logging。
替代文字http://www.gitready.comhttp://img.dovov.comsquash1.png
如果把最后4次提交包装在一起,会更快乐
$ git rebase -i HEAD~4 pick 01d1124 Adding license pick 6340aaa Moving license into its own file pick ebfd367 Jekyll has become self-aware. pick 30e0ccb Changed the tagline in the binary, too. # Rebase 60709da..30e0ccb onto 60709da # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. #
使用头HEAD〜4的最后四个提交来重新
HEAD~4
。
我们只是将所有东西压缩到一个提交。
所以,把文件的前四行改成这个就行了:
pick 01d1124 Adding license squash 6340aaa Moving license into its own file squash ebfd367 Jekyll has become self-aware. squash 30e0ccb Changed the tagline in the binary, too.
基本上,这告诉Git将所有四个提交合并到列表中的第一个提交。 一旦完成并保存,另一个编辑器popup如下:
# This is a combination of 4 commits. # The first commit's message is: Adding license # This is the 2nd commit message: Moving license into its own file # This is the 3rd commit message: Jekyll has become self-aware. # This is the 4th commit message: Changed the tagline in the binary, too. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # Explicit paths specified without -i nor -o; assuming --only paths... # Not currently on any branch. # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: LICENSE # modified: README.textile # modified: Rakefile # modified: bin/jekyll #
由于我们合并了这么多的提交,所以Git允许您根据进程中涉及的其他提交来修改新提交的消息。 按照您认为合适的方式编辑消息,然后保存并退出。
一旦完成,你的提交已经成功地被压扁了!
Created commit 0fc4eea: Creating license file, and making jekyll self-aware. 4 files changed, 27 insertions(+), 30 deletions(-) create mode 100644 LICENSE Successfully rebased and updated refs/heads/master.
如果我们再看历史
替代文字http://www.gitready.comhttp://img.dovov.comsquash2.png
注意:为了“ 压缩 ”目的, Git1.7 (2010年2月)推出了两个新元素(如Dustin在评论中提到的):
- “
git rebase -i
”学到了新的动作“fixup
”,它压缩了变化,但不影响现有的日志信息。- “
git rebase -i
”也学到了 –--autosquash
选项,与新的“fixup”操作一起使用。
这两个(fixup行动和 – --autosquash
选项)在这个Thechnosorcerynetworking博客条目中说明 。 自2009年6月份以来,这些function一直在进行烹调,并在去年12月进一步辩论
fixup
动作或指令是用来压扁你在rebase --interactive
的提交编辑列表中手动重新sorting的提交,而忽略第二个提交消息,这将使得消息编辑步骤更快(你可以保存它:压扁的提交将只有第一个提交信息)
由此产生的提交消息将只是第一次提交。
# s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message
--autosquash
选项是为你自动进行提交重新sorting的过程:
如果你知道你想要压缩什么,你可以提交一个“
squash! $other_commit_subject
squash! $other_commit_subject
“。 然后,如果您运行@git rebase --interactive --autosquash commitish@
,则该行将自动设置为压扁,并放置在$ other_commit_subject主题的提交下方。
(实际上, squash!
只能使用另一个提交信息的开始 )
$ vim Foo.txt $ git commit -am "Change all the 'Bar's to 'Foo's" [topic 8374d8e] Change all the 'Bar's to 'Foo's 1 files changed, 2 insertions(+), 2 deletions(-) $ vim Bar.txt $ git commit -am "Change all the 'Foo's to 'Bar's" [topic 2d12ce8] Change all the 'Foo's to 'Bar's 1 files changed, 1 insertions(+), 1 deletions(-) $ vim Foo.txt $ git commit -am "squash! Change all the 'Bar's" [topic 259a7e6] squash! Change all the 'Bar's 1 files changed, 2 insertions(+), 1 deletions(-)
看到? 这里第三次提交只使用第一个提交消息的开头。
一个rebase --interactive --autosquash
会把被压扁的提交移动到相关的那个之下:
pick 8374d8e Change all the 'Bar's to 'Foo's squash 259a7e6 squash! Change all the 'Bar's pick 2d12ce8 Change all the 'Foo's to 'Bar's
消息版本将是:
# This is a combination of 2 commits. # The first commit's message is: Change all the 'Bar's to 'Foo's # This is the 2nd commit message: squash! Change all the 'Bar's
默认情况下,您将保持提交消息中logging的压缩操作。
但是,修复! 指令,你可以在提交消息中保持压缩状态“不可见”,同时还可以通过使用--autosquash
选项自动执行重新sorting(以及第二个提交消息基于你想要压缩的第一个提交的事实) )。
pick 8374d8e Change all the 'Bar's to 'Foo's fixup cfc6e54 fixup! Change all the 'Bar's pick 2d12ce8 Change all the 'Foo's to 'Bar's
该消息默认是:
# This is a combination of 2 commits. # The first commit's message is: Change all the 'Bar's to 'Foo's # The 2nd commit message will be skipped: # fixup! Change all the 'Bar's
注意
fixup!
提交的消息已经被注释掉了。
你可以直接保存消息,原始的提交消息将被保留 。
当你意识到你忘记添加一个早期的提交的一部分,非常方便包括更改 。
现在,如果您想根据之前的提交进行修复或压缩 , Jacob Helwig (Technosorcery Networks博客条目的作者)build议使用以下别名:
[alias] fixup = !sh -c 'git commit -m \"fixup! $(git log -1 --format='\\''%s'\\'' $@)\"' - squash = !sh -c 'git commit -m \"squash! $(git log -1 --format='\\''%s'\\'' $@)\"' -
而为了做一个rebase互动,总是会受益于意图被压扁的提交的自动重新sorting:
[alias] ri = rebase --interactive --autosquash
使用软重置而不是重新压缩GIT历史
我认为VonC答案的长度是字面意思,就是说git rebase
是多么复杂。 这是我对我的一个问题的另一个答案的延伸。
- 你有一个分支机构
ticket-201
,你从master
分支。 你想假装从ticket-201
提交的所有提交都没有发生过,但是你完成了所有的工作。 - 软重置到分支点使用
git reset --soft hash
其中hash
应该是一个提交散列在ticket-201
的日志。 - 使用添加然后提交来提交您的更改。 现在分支历史将只有第一次提交和新的东西。
从不同分支的任意承诺看历史
使用重置,您可以重新编写历史logging,尽pipe您的编辑将失去拥有正确时间戳的魅力。 假设你不关心它(文件上的时间/date就足够了,也许?),或者如果你想提交提交,你可以按照下面的步骤:
- 签出一个新的分支在
commit0
(假装这是一个散列):git checkout -b new-history commit0
- 现在你可以从
commit5
获得文件:git reset --hard commit5
- 切换回你的索引点:
git reset --soft commit0
- 提交,这将是分支中的第二次提交。
这个想法简单,有效和灵活。
用南瓜代替
最近,我一直在另一个分公司工作,并使用squash
。 另一个分支叫做temp,然后我用git merge temp --squash
把它引入真正的分支,并把它推到服务器端。
工作stream程就像这样,假设我在Ticket65252
工作:
git branch -d temp #remove old temp bbranch git checkout -b temp # work work work, committing all the way git checkout Ticket65252 git merge temp --squash git commit -m "Some message here"
使用rebase
优点 ? 方式较为复杂。
使用reset --hard
优点 – reset --soft
,然后reset --soft
? 不那么容易混淆,而且容易出错。
使用git rebase -i来挑选和挤压你的提交。