在没有交互重基的情况下,在历史记录中压缩两个Git提交



我正在将旧的SVN存储库转换为Git,其中包括尝试将所有分支/标记放在所有正确的位置。这部分进展得很顺利,但是有时我想在脚本的历史记录中添加一个提交,然后我想在下一次提交时删除它。问题是,我不是一个一个地抓取提交,而是作为一个大的组来抓取,所以当我将它们从SVN存储库中取出时,我不能压缩它们。最后,我的存储库看起来像这样:

* (branch_2, HEAD) commit 5
* commit 4
* commit 3
* SQUASH ME!
* (branch_1) commit 2
* commit 1

我希望能够用SQUASH ME!压制commit 3,这显然很容易与交互式重基,但从脚本内更具挑战性。我似乎遇到的主要问题是,虽然很容易检出branch_1或之前的任何提交,但很难以编程方式要求在之后提交,而且我很难预测我需要从branch_2返回多少提交。我真的很想做这样的事情:

git checkout branch_1+2

指针吗?

你说的不是压缩,而是修复,因为压缩会交互式地向你询问提交msg,而修复使用来自HEAD提交的提交消息

这是一个不需要干预的脚本。

脚本:/usr/bin/git-fixup
#/bin/bash
# This command fixesup one commit onto his parent
set -e
# We need a commit from the first argument of that command
commit=${1:?No commit given as first argument}
startingbranch=$(git rev-parse --abbrev-ref HEAD)
# Checkout the parent of the asked commit
git checkout "$commit"
git checkout HEAD~
# Merge the commit into it's parent, keeping the commit message of the parent
git merge --squash "$commit"
git add .
git add --update
git commit --amend --no-edit
# Store the current commit
newcommit=$(git rev-parse HEAD)
# Rebase the starting branch onto the new commit
git checkout "$startingbranch"
git rebase "$newcommit"

连用
git fixup <commit-id>

例如,如果历史记录是:

ce0e2fd (master, HEAD) commit 4
72ab3c4 commit 3
8150939 commit 2
301c1e1 commit 1

你可以做git fixup 72ab3c4,它将"commit 3"one_answers"commit 2"合并在一起,作为一个带有"commit 2"消息的提交,并将你放回主分支。

From git rebase --help:

——autosquash

当提交日志消息以"squash!"……"(或"修正!…"),并且存在标题以相同开头的提交…,自动修改rebase -i的todo列表这样,标记为压缩的提交就在要修改的提交之后出现,并改变被移动的提交的动作从采摘到挤压(或修复)。

此选项仅在使用——interactive选项时有效。

如果输入的格式正确,看起来它可以完成你想要的一半。

另一半是阻止它启动交互式编辑器。幸运的是,编辑器是可配置的,所以我们可以把它设置成无害的。

试试这个:

env EDITOR=true git rebase -i --autosquash <from-here>

将编辑器设置为true(一个简单地成功退出的工具)足以说服git继续默认的重基设置,自动压缩应该设置为有用的东西。


或者,如果--autosquash不做您想要的,您可以将EDITOR设置为您喜欢的任何脚本:

env EDITOR=mysquasher.sh git rebase -i <from-here>

脚本可以做任何您需要的事情,但在您的情况下,它只需要找到包含"SQUASHME!"的每一行,并在下一行更改"pick"以读取"fixup"。使用awk:

可能最容易实现这一点
#!/bin/bash -e
awk -- 'BEGIN {dosquash=0}
        dosquash==1 {gsub(/^pick/, "fixup"); dosquash=0}
        /SQUASHME/ {dosquash=1}
        {print}' "$1" > /tmp/tmp.$$
mv /tmp/tmp.$$ "$1"

最新更新