在没有交互式变基的情况下,将两个Git提交到历史中间

时间:2015-10-01 13:50:31

标签: git git-rebase

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

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

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

git checkout branch_1+2

任何指针?

2 个答案:

答案 0 :(得分:7)

你所说的不是壁球,而是 fixup ,因为壁球会以交互方式询问你提交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合并在一起&#34;提交3&#34;并且&#34;提交2&#34;作为提交消息&#34; commit 2&#34;,并将您放回主分支。

答案 1 :(得分:5)

来自git rebase --help

  

<强> - autosquash

     

当提交日志消息以&#34; squash开头时! ...&#34; (或&#34; fixup!...&#34;),并且有一个提交,其标题以相同的开头   ...,自动修改rebase -i的待办事项列表   因此,标记为压缩的提交在修改提交之后立即生效,并更改已移动提交的操作   从挑选到壁球(或修复)。

     

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

如果输入的格式正确,那看起来它会做你想要的一半。

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

试试这个:

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

将编辑器设置为true(一个只是成功退出的工具)足以说服git继续使用默认的rebase设置,自动壁球应该设置为有用的东西。

或者,如果--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"