我有以下提交历史记录:

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

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


当前回答

对我来说,这是为了从回购中删除一些凭证。我试着换基,在换基的过程中遇到了一大堆看似无关的冲突——继续。不要费心尝试重新设置自己的基础,在mac上使用名为BFG(brew-install-BFG)的工具。

其他回答

我解决了这个问题,

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是不可接受的方法这棵树最终会陷入你们知道其他人不会发生的冲突。如果你愿意为了用更少的提交来保持树的整洁,可以尝试这样做,如果小团队,否则不可取。。。。。

完全非交互式命令(1)

我只是想分享一个我正在使用的别名。它基于非交互式交互式数据库。要将其添加到git中,请运行以下命令(解释如下):

git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"; }; f'

或者,一个也可以处理未暂存文件的版本(通过先暂存,然后再卸载):

git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git stash -k && git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" && git stash pop; }; f'

这个命令的最大优点是它不是vim。


(1) 当然,考虑到重新启动期间没有冲突

用法

git amend-to <REV> # e.g.
git amend-to HEAD~1
git amend-to aaaa1111

将名称修改为似乎合适IMHO。将流程与--修订:

git add . && git commit --amend --no-edit
# vs
git add . && git amend-to <REV>

解释

git-config—全局别名<名称>'<COMMAND>'-创建名为<NAME>的全局git别名,该别名将执行非git命令<COMMAND>f(){<BODY>};f-一个“匿名”bash函数。SHA=`git rev parse“$1”`;-将参数转换为gitrevision,并将结果赋给变量SHAgitcommit--fixup“$SHA”--fixup提交SHA。参见git提交文档GIT_SEQUENCE_EDITOR=true GIT rebase--交互式--autosquash“$SHA^”gitrebase——交互式“$SHA^”部分已被其他答案覆盖。--autosquash与gitcommit一起使用--fixup,有关更多信息,请参阅gitrebase文档GIT_SEQUENCE_EDITOR=true是使整个事情非交互式的原因。这是我从这篇博客文章中学到的。

使用令人惊叹的交互式rebase:

git rebase -i @~9   # Show the last 9 commits in a text editor

找到所需的提交,将pick更改为e(编辑),然后保存并关闭文件。Git将返回到该提交,允许您:

使用gitcommit--修改以进行更改,或使用gitreset@~放弃最后一次提交,但不放弃对文件的更改(即,将您带到编辑文件但尚未提交的位置)。

后者对于执行更复杂的任务(如拆分为多个提交)非常有用。

然后,运行git-rebase--continue,git将在修改后的提交之上回放后续更改。可能会要求您修复一些合并冲突。

注意:@是HEAD的简写,~是指定提交之前的提交。

阅读Git文档中有关重写历史的更多信息。


不要害怕重新启动

ProTip公司™: 不要害怕尝试“危险”的命令来重写历史*-默认情况下,Git不会在90天内删除您的提交;你可以在reflog中找到它们:

$ 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

*注意一些选项,比如硬和强制,它们可以丢弃数据。*此外,不要重写您正在合作的任何分支的历史。



在许多系统上,git-rebase-i将默认打开Vim。Vim不像大多数现代文本编辑器那样工作,所以看看如何使用Vim重新设置基础。如果您希望使用不同的编辑器,请使用git-config--global-core.editor或您最喜欢的文本编辑器对其进行更改。

采用这种方法(它可能与使用交互式rebase完全相同),但对我来说,这有点简单。

注:我提出这种方法是为了说明你能做什么,而不是日常的选择。因为它有很多步骤(可能还有一些警告)

假设您要更改提交0,并且您当前处于功能分支

some-commit---0---1---2---(feature-branch)HEAD

签出此提交并创建一个快速分支。您还可以将功能分支克隆为恢复点(启动之前)。

?(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

提交更改并签回功能分支

git commit --amend
git checkout feature-branch

现在,您将看到如下内容:

some-commit---0---1---2---(feature-branch)HEAD
           \
             ---0'(quick-branch)

将功能分支重新设置为快速分支(解决过程中的任何冲突)。涂抹涂抹物并移除快速分支。

git rebase quick-branch
git stash pop
git branch -D quick-branch

最后你会得到:

some-commit---0'---1'---2'---HEAD(feature-branch)

Git不会在重基时复制0提交(虽然我不能说在多大程度上)。

注意:所有提交散列都是从我们最初打算更改的提交开始更改的。

基于文档

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

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