如何修改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)的工具。