git rebase squash 获取第二条消息(如修复)
git rebase squash take second message (like fixup)
假设我有一些提交:
<sha1> bug due to function1
<sha2> bug due to function2
... other commits
并且我想将提交 1 和提交 2 压缩在一起,仅保留 second 提交的消息,然后我将使用 git rebase -i
,编辑为:
pick <sha1> bug due to function1
squash <sha2> bug due to function2
... other commits
而且我总是需要编辑合并的消息并删除第一条消息。
我知道我可以重新安排提交并像这样使用 fixup
:
pick <sha2> bug due to function2
fixup <sha1> bug due to function1
pick <sha3> other commit
但是我有这样的风险,颠倒两个提交的顺序,可能会有一些冲突。
我怎样才能以更少的操作获得相同的结果,尤其是避免编辑合并的消息。请注意,在提交 1 之前和提交 2 之后可能有很多提交。
首先执行 git log
查看最后四次提交的哈希值。重置为您要压缩的两次提交之前的最后一次提交:
git reset --hard <sha0>
...您要压缩的两个提交之前的最后一个提交在哪里。
然后,依次尝试以下命令:
git cherry-pick -n <sha1>
git cherry-pick -n <sha2>
git commit
git cherry-pick <sha3>
前两个命令将在您的本地暂存沙箱中组合 <sha1>
和 <sha2>
。当您不带参数执行 git commit
时,它将使用上次提交的提交消息提交更改。您需要做的就是在查看提交消息后退出编辑器。最后的 cherry-pick 应用最后一次提交,未更改。
全自动版本。假设一个 git 历史是这样的:
... (as many commits as you like)
6acdc6f - commit message 3
46c9468 - commit message 2
9b28fd5 - commit message 1
然后变基以将提交 1 和 2 压缩在一起并保留 提交消息 2:
git rebase -i 9b28fd5~
然后像这样编辑:
pick 9b28fd5 commit message 1
pick 46c9468 commit message 2
exec HH=$(git rev-parse HEAD); git reset --soft HEAD~2; git commit -C $HH
pick 6acdc6f commit message 3
shell 命令的简要说明:
HH=$(git rev-parse HEAD) # store the HEAD sha1 in a variable; since the next call will change HEAD to HEAD~2
git reset --soft HEAD~2 # destroy the last two commits keeping the changes staged.
git commit -C $HH # now commit all changes reusing the commit message from commit2 (using the sha1 that we saved in the variable)
由于 OP 的问题,请注意交互式变基的行为确实发生了变化(现在已修复,2021 年第一季度)。
当“git rebase -i
"(man)处理fixup insn时,没有理由清理commit log消息,但是我们做了通常的stripspace处理。
Git 2.31(2021 年第一季度)已更正此问题。
参见 commit f7d42ce (28 Jan 2021) by Johannes Schindelin (dscho
)。
(由 Junio C Hamano -- gitster
-- in commit 7e94720 合并,2021 年 2 月 10 日)
rebase -i
: do leave commit message intact in fixup! chains
Reported-by: Vojtěch Knyttl
Helped-by: Martin Ågren
Signed-off-by: Johannes Schindelin
In 6e98de7 ("sequencer (rebase -i): add support for the 'fixup' and 'squash' commands", 2017-01-02, Git v2.12.0-rc0 -- merge listed in batch #8), this developer introduced a change of behavior by mistake: when encountering a fixup!
commit (or multiple fixup!
commits) without any squash!
commit thrown in, the final git commit
(man) was invoked with --cleanup=strip
.
Prior to that commit, the commit command had been called without that --cleanup
option.
Since we explicitly read the original commit message from a file in that case, there is really no sense in forcing that clean-up.
We actually need to actively suppress that clean-up lest a configured commit.cleanup
may interfere with what we want to do: leave the commit message unchanged.
假设我有一些提交:
<sha1> bug due to function1
<sha2> bug due to function2
... other commits
并且我想将提交 1 和提交 2 压缩在一起,仅保留 second 提交的消息,然后我将使用 git rebase -i
,编辑为:
pick <sha1> bug due to function1
squash <sha2> bug due to function2
... other commits
而且我总是需要编辑合并的消息并删除第一条消息。
我知道我可以重新安排提交并像这样使用 fixup
:
pick <sha2> bug due to function2
fixup <sha1> bug due to function1
pick <sha3> other commit
但是我有这样的风险,颠倒两个提交的顺序,可能会有一些冲突。
我怎样才能以更少的操作获得相同的结果,尤其是避免编辑合并的消息。请注意,在提交 1 之前和提交 2 之后可能有很多提交。
首先执行 git log
查看最后四次提交的哈希值。重置为您要压缩的两次提交之前的最后一次提交:
git reset --hard <sha0>
...您要压缩的两个提交之前的最后一个提交在哪里。
然后,依次尝试以下命令:
git cherry-pick -n <sha1>
git cherry-pick -n <sha2>
git commit
git cherry-pick <sha3>
前两个命令将在您的本地暂存沙箱中组合 <sha1>
和 <sha2>
。当您不带参数执行 git commit
时,它将使用上次提交的提交消息提交更改。您需要做的就是在查看提交消息后退出编辑器。最后的 cherry-pick 应用最后一次提交,未更改。
全自动版本。假设一个 git 历史是这样的:
... (as many commits as you like)
6acdc6f - commit message 3
46c9468 - commit message 2
9b28fd5 - commit message 1
然后变基以将提交 1 和 2 压缩在一起并保留 提交消息 2:
git rebase -i 9b28fd5~
然后像这样编辑:
pick 9b28fd5 commit message 1
pick 46c9468 commit message 2
exec HH=$(git rev-parse HEAD); git reset --soft HEAD~2; git commit -C $HH
pick 6acdc6f commit message 3
shell 命令的简要说明:
HH=$(git rev-parse HEAD) # store the HEAD sha1 in a variable; since the next call will change HEAD to HEAD~2
git reset --soft HEAD~2 # destroy the last two commits keeping the changes staged.
git commit -C $HH # now commit all changes reusing the commit message from commit2 (using the sha1 that we saved in the variable)
由于 OP 的问题,请注意交互式变基的行为确实发生了变化(现在已修复,2021 年第一季度)。
当“git rebase -i
"(man)处理fixup insn时,没有理由清理commit log消息,但是我们做了通常的stripspace处理。
Git 2.31(2021 年第一季度)已更正此问题。
参见 commit f7d42ce (28 Jan 2021) by Johannes Schindelin (dscho
)。
(由 Junio C Hamano -- gitster
-- in commit 7e94720 合并,2021 年 2 月 10 日)
rebase -i
: do leave commit message intact in fixup! chainsReported-by: Vojtěch Knyttl
Helped-by: Martin Ågren
Signed-off-by: Johannes Schindelin
In 6e98de7 ("sequencer (rebase -i): add support for the 'fixup' and 'squash' commands", 2017-01-02, Git v2.12.0-rc0 -- merge listed in batch #8), this developer introduced a change of behavior by mistake: when encountering a
fixup!
commit (or multiplefixup!
commits) without anysquash!
commit thrown in, the finalgit commit
(man) was invoked with--cleanup=strip
.
Prior to that commit, the commit command had been called without that--cleanup
option.Since we explicitly read the original commit message from a file in that case, there is really no sense in forcing that clean-up.
We actually need to actively suppress that clean-up lest a configured
commit.cleanup
may interfere with what we want to do: leave the commit message unchanged.