我有以下提交历史记录:
头部头部~头部~2头部~3
gitcommit--修改当前HEAD提交。但是如何修改HEAD~3?
我有以下提交历史记录:
头部头部~头部~2头部~3
gitcommit--修改当前HEAD提交。但是如何修改HEAD~3?
当前回答
采用这种方法(它可能与使用交互式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 commit --amend
// or
git commit --amend -m "an updated commit message"
不修改公共承诺修改后的提交实际上是全新的提交,以前的提交将不再位于当前分支上。
例如,如果您想更改最后三个提交消息或该组中的任何一个提交消息,您可以向git rebase-i提供一个参数,该参数是您要编辑的最后一个提交的父级,即HEAD~2^或HEAD~3。记住~3可能更容易,因为您正在尝试编辑最后三次提交,但请记住,您实际上是在指定四次提交之前,即您要编辑的最后一次提交的父级:
$ git rebase -i 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。
使用令人惊叹的交互式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或您最喜欢的文本编辑器对其进行更改。
自动交互式重新基础编辑,然后提交恢复,以备重做
我发现自己经常修复一个过去的错误,为此我写了一个脚本。
以下是工作流程:
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
git存储+再基础自动化
因为当我需要多次修改Gerrit审查的旧提交时,我一直在做:
git-amend-old() (
# Stash, apply to past commit, and rebase the current branch on to of the result.
current_branch="$(git rev-parse --abbrev-ref HEAD)"
apply_to="$1"
git stash
git checkout "$apply_to"
git stash apply
git add -u
git commit --amend --no-edit
new_sha="$(git log --format="%H" -n 1)"
git checkout "$current_branch"
git rebase --onto "$new_sha" "$apply_to"
)
GitHub上游。
用法:
修改源文件,如果已在repo中,则无需gitaddgit修改旧$old_sha
我很喜欢这一点,因为它不会挤压其他无关的修复。