web-dev-qa-db-ja.com

git rebase --interactiveを非インタラクティブに実行するにはどうすればよいですか?

以下を行うことは可能ですか?

  1. git rebase --interactiveを作成して、標準のボイラープレートをファイルに出力するだけでなく、ファイルに出力してエディターで開くようにします。
  2. ユーザーがファイルを編集できるようにします。
  3. 編集したファイルの名前でgit rebaseを再実行してもらいます。
  4. 通常のリベースプロセスを続行します。

ユースケース:もちろん、スクリプトによるリベース。 たとえば、Gitでコミットを非対話的に並べ替える方法 を参照してください。

43
pfalcon

いくつかの考えと調査の後、答えは取るに足らないものであることがわかりました: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>は単一の引数、つまり標準のリベースコミットリストを含むファイルへのパスを受け入れる必要があります。インプレースで書き換えて終了する必要があります。その後、通常のリベース処理が行われます。

54
pfalcon

@pfalconの答えに追加すると、sedをGIT_SEQUENCE_EDITORとして使用できます。たとえば、私は各コ​​ミットを編集したかったので、これを行いました:

GIT_SEQUENCE_EDITOR="sed -i -re 's/^pick /e /'" git rebase -i
11
Leif Wickland

Pfalconの答えを拡張する:

GIT_SEQUENCE_EDITOR=<script> git rebase -i <params>を実行します。 <script>は単一の引数を受け入れる必要があります-標準のリベースコミットリストを含むファイルへのパス。スクリプトはそれをその場で書き換えて終了します。その後、通常のリベース処理が行われます。

必要なコンテンツを含む環境変数がある場合:

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

ファイルのキャットも機能します:

GIT_SEQUENCE_EDITOR='cat rebase_data_file >' git rebase -i [<additional params>]
7
James Foucar

私はこのスクリプトを使用します(追加すると、コミット分割を簡素化できます)。

#!/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
git merge-base --is-ancestor $COMMIT HEAD || 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
6

インタラクティブモードでは、セットエディターを操作できます。
使用中のエディターは、次のようにして取得できます。

git config --get core.editor

したがって、non-interactiveエディターを設定した場合、それはstdinでコマンドを受け入れるエディターであり、--interactive in a non-interactive way :)
私は確かに知っていますvimもコマンドを受け入れます標準エディタed、もちろんです。

そのため、インタラクティブエディタを保持します(必要な場合)。

$ 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"
4
c00kiemon5ter

touchを編集者として使用して、ファイルを変更して表示されるようにすることができます。例えば

GIT_SEQUENCE_EDITOR=touch git rebase -i [commit]

エイリアスするには、baselineをリベースしたいタグとして指定します

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

エイリアスは、実行中のシェルがbashではなくcmdであるため、Windowsで機能します。

4

私は解決策を見つけました。以下を使用できます。

$ GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash $COMMIT_HASH~1
0
Wooseong Kim

他の人が述べたように、インタラクティブなリベースファイルを変更するカスタムGIT_SEQUENCE_EDITOR値を提供する必要があります。単一のコミットでアクションを実行するだけの場合は、次のように実行できます。

# Runs "edit" on HEAD~3
GIT_SEQUENCE_EDITOR="sed -i -ze 's/^pick/edit/'" git rebase -i HEAD~3

または、これを一般化する関数は次のとおりです。

# Usage: git-rebase-custom edit HEAD~3
git-rebase-custom() {
    local action=$1
    shift

    GIT_SEQUENCE_EDITOR="sed -i -ze 's/^pick/$action/'" git rebase -i "$@"
}