我把我的历史搞砸了,想对它做些修改。问题是,我有一个包含两个不相关更改的提交,并且这个提交被本地(非推送的)历史记录中的一些其他更改包围。
我想在推出这个提交之前拆分它,但我看到的大多数指南都与拆分最近的提交或未提交的本地更改有关。对一个在历史中隐藏了一点的提交执行此操作,而不必从那时起“重新执行”我的提交,这可行吗?
如果你还没有推送,只需使用git rebase。更好的方法是使用git rebase -i来交互式地移动提交。您可以将有问题的提交移到前面,然后根据需要将其拆分并将补丁移到后面(如果需要的话)。
git rebase
git rebase -i
这里有一个关于拆分提交在rebase manpage中的指南。简要总结如下:
执行包括目标提交(例如git rebase -i <commit-to-split>^ branch)在内的交互式rebase,并将其标记为可编辑。
git rebase -i <commit-to-split>^ branch
当rebase到达提交时,使用git reset HEAD^重置到提交之前,但保持你的工作树完整。
git reset HEAD^
增量地添加更改并提交它们,根据需要进行尽可能多的提交。add -p可以用于仅在给定文件中添加部分更改。使用commit -c ORIG_HEAD如果你想在某个提交中重用原始的提交消息。
add -p
commit -c ORIG_HEAD
如果你想测试你提交的内容(好主意!),使用git stash来隐藏你还没有提交的部分(或者在你提交之前使用stash --keep-index), test,然后git stash pop将其余部分返回到工作树。继续提交,直到你提交了所有的修改,即有一个干净的工作树。
git stash
stash --keep-index
git stash pop
运行git rebase --continue继续在现在拆分的提交之后应用提交。
git rebase --continue
要分割一个提交<commit>并添加在此之前重新提交,并保存<commit>的作者日期,-步骤如下:
<commit>
编辑提交之前 <commit>
git rebase -i <commit>^^
注:也许还需要编辑<commit>
樱桃选择<commit>到索引
git cherry-pick -n <commit>
Interactively reset unneeded changes from the index and reset the working tree
git reset -p && git checkout-index -f -a
作为替代,只需交互式地保存不需要的更改:git stash push -p -m "tmp other changes"
git stash push -p -m "tmp other changes"
git commit -m "upd something" .
可选地,重复第2-4项以添加更多的中间提交
下面是如何使用Magit。
比如提交ed417ae是你想要修改的;它包含两个不相关的更改,并隐藏在一个或多个提交之下。点击ll来显示日志,并导航到ed417ae:
ll
然后点击r打开rebase弹出框
r
和m来修改提交点。
m
注意在你想要拆分的提交中@现在是怎样的——这意味着HEAD现在在提交中:
@
我们想要将HEAD移动到父节点,因此导航到父节点(47e18b3)并点击x (magit-reset-quickly,如果你使用evil-magit,则绑定到o),然后输入“是的,我的意思是在点提交”。您的日志现在应该如下所示:
x
magit-reset-quickly
evil-magit
o
现在,点击q进入常规的Magit状态,然后使用常规的unstage u命令取消第一次提交中没有出现的内容,照常提交c其余部分,然后stage和commit第二次提交中出现的内容,完成后:点击r打开rebase弹出窗口
q
u
c
s
和另一个r继续,你就完成了!ll现在显示:
如果你只想从一个文件中提取内容,还有一个更快的版本。它更快,因为交互式rebase实际上不再是交互式的(当然,如果您想从上次提交中提取,那么根本不需要rebase,那么它甚至更快)
the_file
删除索引:
git add the_file
Restore the lines you just deleted back into the file without affecting the index!
git show HEAD:./the_file > the_file
"SHA1" is the commit you want to extract the lines from:
git commit -m 'fixup! SHA1'
Create the second, brand new commit with the content to extract restored by step 3:
git commit -m 'second and new commit' the_file
Don't edit, don't stop/continue - just accept everything:
git rebase --autosquash -i SHA1~1
Of course even faster when the commit to extract from is the last commit:
4. git commit -C HEAD --amend 5. git commit -m 'second and new commit' thefile 6. no rebase, nothing
如果你使用magit,那么步骤4、5和6是一个单独的动作:提交,立即修复
magit
在某些情况下,手动纠正历史也可以。
我更喜欢使用我的git GUI(而不是命令行),我有问题的提交只提交了3次,我还没有推送任何文件,下面的文件也不完全整洁,所以我选择通过精选完全重建所有文件,这比通过命令行使用交互式rebase编辑更快,但方法相似。
下面是我如何在我最喜欢的git GUI(我个人使用SourceTree)中做到这一点: