2012-09-12 72 views
31

可以做以下吗?如何以非交互方式运行git rebase --interactive?

  1. git rebase --interactive只输出标准的样板到一个文件中,而不是输出到文件,并在编辑器中打开它。
  2. 让用户编辑文件。
  3. 让用户用编辑文件的名称重新运行git rebase
  4. 继续平常的rebase进程。

用例:脚本重新绑定当然。例如,请参阅how to re-order commits in Git non-interactively

+0

请参阅http://stackoverflow.com/questions/12270357/really-flatten-a-git-merge这也是有用的。 – pfalcon

+0

除了下面的git rebase,git filter-branch是另一个选项:http://stackoverflow.com/questions/19636750/git-filter-branch-msg-filter-to-reword-a-pushed-commit-message – MarcH

回答

41

经过一番思考和研究后,结果变得微不足道:git rebase -i从知名的EDITOR/VISUAL环境变量中获取编辑名称,因此覆盖指向非交互式脚本来完成这项工作。

但是,EDITOR/VISUAL无所谓地应用于提交列表,在重新提供字词时提交消息等等。所以,自http://git.kernel.org/?p=git/git.git;a=commit;h=821881d88d3012a64a52ece9a8c2571ca00c35cd以来,有一个特殊的环境变量GIT_SEQUENCE_EDITOR,它仅适用于提交列表。

所以,配方重新排序或压扁的提交是:

运行:GIT_SEQUENCE_EDITOR=<script> git rebase -i <params>。 你的<script>应该接受一个参数:包含标准rebase提交列表的文件的路径。它应该重写它并退出。之后通常会发生rebase处理。

+0

没有知道'GIT_SEQUENCE_EDITOR',看起来很有用;) – c00kiemon5ter

+2

或者,不要为此唯一目的创建脚本,只需使用现有的命令'true',它忽略任何参数并具有固定的返回码'0'。 –

+3

@me_并且这只有在你没有实际重新提交提交时想要执行'rebase -i'时才有用。 –

2

交互模式提示设置编辑器使用。
在使用编辑器可以用检索:

git config --get core.editor 

所以,如果你设置了非交互式编辑器 - 这是接受标准输入命令的编辑器,可以在非与--interactive工作 - 交互方式:)
我知道肯定vim接受命令,标准编辑器ed,ofcourse。

所以,保持交互式编辑器(如果想)

$ ied="$(git config --get core.editor)" 

设置的非交互式编辑

$ git config --unset-all core.editor 
$ git config --add core.editor ed 

,并用它做的工作..

$ printf '%s\n' "some-ed-cmd" "another-ed-cmd" "wq" | git rebase -i HEAD~5 

和恢复编辑(如果需要)

$ git config --unset-all core.editor 
$ git config --add core.editor "$ied" 
+0

谢谢,我们可能在类似的时间开始写答案,在我发布我之前我没有看到你的答案;-) – pfalcon

+0

我认为在每个会话或每个命令的基础上重新定义EDITOR会更简单。 – MarcH

+1

我强烈建议不要做'git config --unset-all'或其他可以修改脚本中用户配置文件的内容。要为一个命令设置git配置变量,请使用'git -c var = val',在这种情况下,设置'EDITOR'要简单得多。它是一个环境变量,仅适用于当前进程,不会干扰其他进程或将任何内容写入磁盘。 –

4

添加到@ pfalcon的答案,您可以使用sed作为您的GIT_SEQUENCE_EDITOR。例如,我想编辑每个提交,所以我这样做:

GIT_SEQUENCE_EDITOR="sed -i -re 's/^pick /e /'" git rebase -i 
4

我使用这个脚本(它添加允许简化犯分裂):

#!/bin/bash 

ACTION=$1 
COMMIT=$(git rev-parse --short $2) 
[[ "$COMMIT" ]] || exit 1 
CORRECT= 
for A in p pick r reword e edit s squash f fixup x exec d delete t split; do 
    [[ $ACTION == $A ]] && CORRECT=1 
done 
[[ "$CORRECT" ]] || exit 1 
if [[ $ACTION == "delete" || $ACTION == "d" ]]; then 
    GIT_SEQUENCE_EDITOR="sed -i -e '/^pick $COMMIT/d'" git rebase -i $COMMIT^^ 
elif [[ $ACTION == "split" || $ACTION == "t" ]]; then 
    GIT_SEQUENCE_EDITOR="sed -i -e 's/^pick $COMMIT/edit $COMMIT/'" git rebase -i $COMMIT^^ || exit 1 
    git reset --soft HEAD^ 
    echo "Hints:" 
    echo " Select files to be commited using 'git reset', 'git add' or 'git add -p'" 
    echo " Commit using 'git commit -c $COMMIT'" 
    echo " Finish with 'git rebase --continue'" 
else 
    GIT_SEQUENCE_EDITOR="sed -i -e 's/^pick $COMMIT/$1 $COMMIT/'" git rebase -i $COMMIT^^ 
fi 

添加一个别名到您。 gitconfig:

[alias] 
    autorebase = ! path_to_your_script 
5

扩展在pfalcon的回答是:

运行GIT_SEQUENCE_EDITOR=<script> git rebase -i <params><script>应接受单个参数 - 包含标准rebase提交列表的文件路径。脚本应该重写它并退出。之后通常会发生rebase处理。

如果你有一个包含内容的环境变量,你想:

GIT_SEQUENCE_EDITOR='echo "$REBASE_DATA" >' git rebase -i [<additional params>] 

Catting文件将工作太:

GIT_SEQUENCE_EDITOR='cat rebase_data_file >' git rebase -i [<additional params>] 
2

您可以使用touch因为这将触及编辑器该文件将会出现修改。例如

GIT_SEQUENCE_EDITOR=touch git rebase -i [commit] 

别名它,给baseline作为标签我要变基对

git config alias.baseline '!GIT_SEQUENCE_EDITOR=touch git rebase -i baseline' 

,Windows下的别名工作,因为它正在执行的外壳是bashcmd

+0

这适用于'git --interactive --exec '。我将''设置为运行由我的分支引入或修改的测试的命令,并且将''设置为'master'。这会导致git针对分支中的每个提交运行我的测试。 – Mike

0

基于Jezz's answer, 我制成的外壳无关的脚本(GitReb) ,其与多个参数的版本工作, :/<text>语法,根提交和也做一些完整性检查。

我也做了更简单,除去t/split行动 和delete - >drop转换 其中IMO超出这个脚本的范围。

相关问题