如何修改git中的指定提交?
我通常会提交一个提交列表以供审查。 如果我有:
HEAD
-
Commit3
-
Commit2
-
Commit1
我知道我可以使用git commit --amend
修改头部提交,但是如何修改Commit1
,因为它不是HEAD
提交?
你可以使用git rebase,例如,如果你想修改回提交bbc643cd
,运行
$ git rebase --interactive 'bbc643cd^'
在默认编辑器中,修改要edit
的提交行中的pick
edit
。 进行更改,然后用与之前相同的消息进行提交:
$ git commit --all --amend --no-edit
修改提交,之后
$ git rebase --continue
返回到前面的头提交。
警告 :请注意,这将改变该提交的SHA-1 以及所有的孩子 – 换句话说,这将重写这一点的历史。 如果您使用git push --force
命令进行git push --force
则可以打破这个做法
使用真棒互动rebase:
git rebase -i @~9 # Show the last 9 commits in a text editor
find你想要的提交,把pick
改为e
( edit
),然后保存并closures文件。 Git会回滚到提交,允许你:
- 使用
git commit --amend
来进行更改,或者 - 使用
git reset @~
放弃最后一次提交,而不是对文件的更改(即带你到你编辑文件但尚未提交时的位置)。
后者对于做更复杂的东西比如分裂成多个提交是有用的。
然后,运行git rebase --continue
,然后Git会在修改的提交之上重播后续的更改。 您可能会被要求解决一些合并冲突。
注意: @
是HEAD
缩写, ~
是指定提交之前的提交。
阅读更多关于在Git文档中重写历史logging的信息。
不要害怕变硬
ProTip™:不要害怕尝试重写历史logging的“危险”命令* – 默认情况下,Git不会删除90天的提交; 你可以在reflog中find它们:
$ git reset @~3 # go back 3 commits $ git reflog c4f708b HEAD@{0}: reset: moving to @~3 2c52489 HEAD@{1}: commit: more changes 4a5246d HEAD@{2}: commit: make important changes e8571e4 HEAD@{3}: commit: make some changes ... earlier commits ... $ git reset 2c52489 ... and you're back where you started
* 注意,像 – --hard
和--force
这样的选项 – 他们可以丢弃数据。
另外,不要在你正在合作的分支上重写历史logging。
在很多系统上, git rebase -i
会默认打开Vim。 Vim不像大多数现代文本编辑器一样工作,所以看看如何使用Vim进行重新devise 。 如果你想使用不同的编辑器,可以使用git config --global core.editor your-favorite-text-editor
。
使用--autosquash
交互式--autosquash
是我经常使用的,当我需要在历史中更深入地修正以前的提交时。 它本质上加速了ZelluX的答案所展现的过程,当您需要编辑多个提交时特别方便。
从文档:
--autosquash
当提交日志消息以“squash!…”(或“fixup!…”)开始,并且有一个标题以相同的开头的提交时,自动修改rebase -i的待办事项列表,以便提交标记为压扁之后立即提交进行修改
假设你有这样的历史:
$ git log --graph --oneline * b42d293 Commit3 * e8adec4 Commit2 * faaf19f Commit1
并且您有要更改为Commit2的更改,然后使用提交您的更改
$ git commit -m "fixup! Commit2"
或者你可以使用commit-sha而不是提交消息,所以"fixup! e8adec4
甚至只是提交消息的前缀。
然后在之前的提交上启动一个交互式底图
$ git rebase e8adec4^ -i --autosquash
你的编辑器将打开提交已经正确的命令
pick e8adec4 Commit2 fixup 54e1a99 fixup! Commit2 pick b42d293 Commit3
所有你需要做的是保存并退出
跑:
$ git rebase --interactive commit_hash^
每个^
表示你想要编辑的提交数量,如果它只有一个(你指定的提交哈希),那么你只需要添加一个^
。
使用Vim,你可以改变你想要改变的提交,保存并退出( :wq
)。 然后git会提示你每次提交你标记为reword,所以你可以改变提交信息。
每个提交信息你必须保存并退出( :wq
)才能进入下一个提交信息
如果您想退出而不应用更改,请按:q!
编辑 :在vim
导航你使用j
上去, k
下去, h
走左, l
走右(所有这些在正常模式下,按ESC
进入正常模式)。 要编辑文本,请按i
以便进入插入文本的INSERT
模式。 按ESC
返回到正常模式:)
更新 :这是github上市的一个很好的链接如何使用git来撤销(几乎)任何东西
如果由于某种原因你不喜欢交互式编辑器,你可以使用git rebase --onto
。
假设你想修改Commit1
。 首先,从以前的分支Commit1
:
git checkout -b amending [commit before Commit1]
其次,用cherry-pick
抓住Commit1
:
git cherry-pick Commit1
现在,修改您的更改,创buildCommit1'
:
git add ... git commit --amend -m "new message for Commit1"
最后,在隐藏其他更改之后,将其余的提交移植到新的提交之上:
git rebase --onto amending Commit1 master
阅读:“ amending
分支, amending
Commit1
(不包括)和master
(包含)之间的所有提交”。 也就是Commit2和Commit3,完全删除旧的Commit1。 你可以挑选他们,但这种方式更容易。
记得清理你的分支!
git branch -d amending
来到这种方法(它可能是完全相同的使用交互式底座),但对我来说,这是一种直截了当的。
注意:为了说明您可以做什么而不是日常的select,我提出了这种方法。 由于它有很多步骤(可能还有一些注意事项)。
假设你想改变提交0
,你目前在feature-branch
some-commit---0---1---2---(feature-branch)HEAD
结帐到这个提交并创build一个quick-branch
。 您也可以将function分支克隆为恢复点(开始之前)。
?(git checkout -b feature-branch-backup) git checkout 0 git checkout -b quick-branch
你现在有这样的东西:
0(quick-branch)HEAD---1---2---(feature-branch)
阶段变化,藏匿一切。
git add ./example.txt git stash
提交更改并签出feature-branch
git commit --amend git checkout feature-branch
你现在有这样的东西:
some-commit---0---1---2---(feature-branch)HEAD \ ---0'(quick-branch)
将feature-branch
到quick-branch
(解决沿途的任何冲突)。 应用存储并删除quick-branch
。
git rebase quick-branch git stash pop git branch -D quick-branch
最后你会得到:
some-commit---0'---1'---2'---HEAD(feature-branch)
Git将不会重复(虽然我不能确定在什么程度上)0重新绑定时提交。
注意:所有提交散列都是从我们最初打算改变的提交开始改变的。
对我来说,这是为了从回购中删除一些凭据。 我尝试重新绑定,并在尝试重新绑定时遇到了大量看似无关的冲突 – 继续。 不要打扰企图改变自己,在mac上使用名为BFG(brew install bfg)的工具。