我有以下提交历史记录:
头部头部~头部~2头部~3
gitcommit--修改当前HEAD提交。但是如何修改HEAD~3?
我有以下提交历史记录:
头部头部~头部~2头部~3
gitcommit--修改当前HEAD提交。但是如何修改HEAD~3?
当前回答
要获得非交互式命令,请在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>。当然,如果您遇到冲突,它仍然是交互式的。
其他回答
采用这种方法(它可能与使用交互式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提交(虽然我不能说在多大程度上)。
注意:所有提交散列都是从我们最初打算更改的提交开始更改的。
当我需要更深入地修复历史中以前的提交时,我经常使用交互式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
你只需要保存并退出
自动交互式重新基础编辑,然后提交恢复,以备重做
我发现自己经常修复一个过去的错误,为此我写了一个脚本。
以下是工作流程:
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
Run:
$git rebase--交互式commit_hash^
每个^表示要编辑的提交次数,如果只有一个(指定的提交哈希),则只需添加一个^。
使用Vim,您可以更改要更改、保存和退出的提交的单词pick to reword(:wq)。然后git将提示您标记为reword的每个提交,以便您可以更改提交消息。
您必须保存并退出(:wq)以转到下一个提交消息的每个提交消息
如果要退出而不应用更改,请按:q!
编辑:要在vim中导航,请使用j向上,k向下,h向左,l向右(所有这些都在正常模式下,按ESC键转到正常模式)。要编辑文本,请按i以进入INSERT模式,在该模式下插入文本。按ESC返回正常模式:)
更新:这里有一个来自github的链接,列出了如何使用git撤消(几乎)任何操作
我解决了这个问题,
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是不可接受的方法这棵树最终会陷入你们知道其他人不会发生的冲突。如果你愿意为了用更少的提交来保持树的整洁,可以尝试这样做,如果小团队,否则不可取。。。。。