我有以下提交历史记录:

头部头部~头部~2头部~3

gitcommit--修改当前HEAD提交。但是如何修改HEAD~3?


当前回答

使用git-rebase。例如,要修改提交bbc643cd,请运行:

$ git rebase --interactive 'bbc643cd^'

请注意命令末尾的插入符号^,因为您实际上需要在要修改的提交之前重新返回提交。

在默认编辑器中,在提到bbc643cd的行中修改pick以进行编辑。

保存文件并退出。git将解释并自动执行文件中的命令。您将发现自己处于之前创建提交bbc643cd的情况。

此时,bbc643cd是您最后一次提交,您可以很容易地修改它。进行更改,然后使用以下命令进行提交:

$ git commit --all --amend --no-edit

之后,使用以下命令返回到上一个HEAD提交:

$ git rebase --continue

警告:请注意,这将更改该提交的SHA-1以及所有子项——换句话说,这将重写从此点开始的历史。如果使用命令gitpush-force进行推送,则可以断开repos。

其他回答

基于文档

修改旧的或多个提交消息的消息

git rebase -i HEAD~3 

上面显示了当前分支上最后3次提交的列表,如果需要更多,请将3更改为其他内容。列表将类似于以下内容:

pick e499d89 Delete CNAME
pick 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

将pick替换为要更改的每个提交消息之前的改写。假设您更改了列表中的第二个提交,您的文件将如下所示:

pick e499d89 Delete CNAME
reword 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

保存并关闭提交列表文件,这将弹出一个新的编辑器,供您更改提交消息、更改提交消息并保存。

最后,强制推行修改后的承诺。

git push --force

当我需要更深入地修复历史中以前的提交时,我经常使用交互式rebase和--autosquash。它本质上加快了ZelluX的回答所说明的过程,当您需要编辑多个提交时,它特别方便。

根据文档:

--自动撤销当提交日志消息以“squash…​“(或”修复…​“),并且有一个提交的标题以相同的开头…​, 自动修改rebase-i的todo列表,以便标记为挤压的提交在要修改的提交之后立即出现

假设您的历史记录如下:

$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1

并且您有要修改为Commit2的更改,然后使用

$ git commit -m "fixup! Commit2"

或者,您可以使用commit sha而不是commit消息,因此“fixup!e8adec4”或甚至只是commit消息的前缀。

然后在提交之前启动交互式重新基础

$ git rebase e8adec4^ -i --autosquash

编辑器将打开已正确排序的提交

pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3

你只需要保存并退出

我解决了这个问题,

1) 通过使用我想要的更改创建新的提交。。

r8gs4r commit 0

2) 我知道我需要合并哪个提交,即提交3。

因此,gitrebase-i HEAD~4#4表示最近的4次提交(此处提交3位于第4位)

3) 在交互式rebase中,最近的提交将位于底部。它看起来很像,

pick q6ade6 commit 3
pick vr43de commit 2
pick ac123d commit 1
pick r8gs4r commit 0

4) 如果您想与特定的提交合并,我们需要重新排列提交。应该是这样的,

parent
|_child

pick q6ade6 commit 3
f r8gs4r commit 0
pick vr43de commit 2
pick ac123d commit 1

重新排列后,需要将p pick替换为f(fixup将在没有提交消息的情况下进行合并)或s(带有提交消息的压缩合并可能在运行时发生变化)

然后保存你的树。

现在与现有提交合并完成。

注意:除非你自己维护,否则这不是更好的方法。如果你的团队规模很大,重写git是不可接受的方法这棵树最终会陷入你们知道其他人不会发生的冲突。如果你愿意为了用更少的提交来保持树的整洁,可以尝试这样做,如果小团队,否则不可取。。。。。

使用git-rebase。例如,要修改提交bbc643cd,请运行:

$ git rebase --interactive 'bbc643cd^'

请注意命令末尾的插入符号^,因为您实际上需要在要修改的提交之前重新返回提交。

在默认编辑器中,在提到bbc643cd的行中修改pick以进行编辑。

保存文件并退出。git将解释并自动执行文件中的命令。您将发现自己处于之前创建提交bbc643cd的情况。

此时,bbc643cd是您最后一次提交,您可以很容易地修改它。进行更改,然后使用以下命令进行提交:

$ git commit --all --amend --no-edit

之后,使用以下命令返回到上一个HEAD提交:

$ git rebase --continue

警告:请注意,这将更改该提交的SHA-1以及所有子项——换句话说,这将重写从此点开始的历史。如果使用命令gitpush-force进行推送,则可以断开repos。

要获得非交互式命令,请在PATH中放置包含以下内容的脚本:

#!/bin/sh
#
# git-fixup
# Use staged changes to modify a specified commit
set -e
cmt=$(git rev-parse $1)
git commit --fixup="$cmt"
GIT_EDITOR=true git rebase -i --autosquash "$cmt~1"

使用它,先暂存更改(使用gitadd),然后运行gitfixup<commit to modify>。当然,如果您遇到冲突,它仍然是交互式的。