我有以下提交历史记录:

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

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


当前回答

我解决了这个问题,

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

其他回答

如果出于某种原因,您不喜欢交互式编辑器,可以使用gitrebase--on。

假设您要修改Commit1。首先,从Commit1之前分支:

git checkout -b amending [commit before Commit1]

第二,用樱桃核抓取Commit1:

git cherry-pick Commit1

现在,修改您的更改,创建Commit1':

git add ...
git commit --amend -m "new message for Commit1"

最后,在隐藏了任何其他更改后,将其余的提交移植到master之上新提交:

git rebase --onto amending Commit1 master

阅读:“将Commit1(不包括在内)和master(包括在内)之间的所有提交重新纳入修改分支”。即Commit2和Commit3,将旧的Commit1完全删除。你可以随便摘,但这样更容易。

记得清理你的树枝!

git branch -d amending

我执行以下操作,包括更改本地提交的日期和时间:

git rebase -i HEAD~6

~6是要显示的提交历史记录的数量。

从pick更改为编辑要编辑的提交。然后我保存并退出(在ubuntu中:Ctrl+O保存,Ctrl+X退出)然后我运行:gitcommit--modify--date=“2022-09-02TT1:10:04”-m“NEW_MSG”如果编辑已打开,只需保存并退出即可。然后,为了确认并转到下一个提交或完成(如果是最后一个),我执行:gitrebase--continue

如果有更多提交要编辑,则从第1点开始重复

最后,我验证更改,如果一切正常,我会推送

使用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。

嗯,这个解决方案可能听起来很愚蠢,但在某些情况下可以拯救你。

我的一个朋友刚刚无意中提交了一些非常大的文件(四个自动生成的文件,每个文件的大小在3GB到5GB之间),然后在此基础上提交了一些额外的代码,然后才意识到git推送不再有效的问题!

这些文件已在.gitignore中列出,但在重命名容器文件夹后,它们被暴露并提交了!现在,在上面还有几次代码提交,但推送一直在运行(试图上传GB的数据!),最终由于Github的文件大小限制而失败。

交互式rebase或任何类似的问题是,他们会处理这些巨大的文件,并且会花费很长时间来做任何事情。然而,在CLI中花了将近一个小时后,我们不确定文件(和增量)是否真的从历史中删除了,或者只是不包括在当前提交中。推也不起作用,我的朋友真的卡住了。

因此,我提出的解决方案是:

将当前git文件夹重命名为~/Project old。再次从github克隆git文件夹(到~/Project)。签出到同一分支。手动将文件从~/Project旧文件夹cp-r到~/Project。确保不需要签入的大量文件被mved并正确包含在.gitignore中。还要确保您没有用旧文件夹覆盖最近克隆的~/Project中的.git文件夹。这就是有问题的历史记录的所在!现在查看更改。它应该是所有最近提交的联合,不包括有问题的文件。最后提交更改,这很好。

这个解决方案最大的问题是,它处理手动复制一些文件,并且它将所有最近的提交合并为一个(显然使用了一个新的提交哈希)

最大的好处是,它在每一步中都非常清晰,它适用于大型文件(以及敏感文件),并且不会在历史上留下任何痕迹!

自动交互式重新基础编辑,然后提交恢复,以备重做

我发现自己经常修复一个过去的错误,为此我写了一个脚本。

以下是工作流程:

git提交编辑<提交哈希>这将在您要编辑的提交时将您丢弃。修复并按您希望的方式进行提交。(您可能希望使用git存储保存来保存未提交的文件)重新提交--修改,如:修改最后一次提交完成重新基准:git rebase—继续

为了实现上述功能,请将以下脚本放入$PATH中名为gitcommitedit的可执行文件中:

#!/bin/bash

set -euo pipefail

script_name=${0##*/}

warn () { printf '%s: %s\n' "$script_name" "$*" >&2; }
die () { warn "$@"; exit 1; }

[[ $# -ge 2 ]] && die "Expected single commit to edit. Defaults to HEAD~"

# Default to editing the parent of the most recent commit
# The most recent commit can be edited with `git commit --amend`
commit=$(git rev-parse --short "${1:-HEAD~}")
message=$(git log -1 --format='%h %s' "$commit")

if [[ $OSTYPE =~ ^darwin ]]; then
  sed_inplace=(sed -Ei "")
else
  sed_inplace=(sed -Ei)
fi

export GIT_SEQUENCE_EDITOR="${sed_inplace[*]} "' "s/^pick ('"$commit"' .*)/edit \\1/"'
git rebase --quiet --interactive --autostash --autosquash "$commit"~
git reset --quiet @~ "$(git rev-parse --show-toplevel)"  # Reset the cache of the toplevel directory to the previous commit
git commit --quiet --amend --no-edit --allow-empty  #  Commit an empty commit so that that cache diffs are un-reversed

echo
echo "Editing commit: $message" >&2
echo