2012-09-12 10 views
31

Ist es möglich, Folgendes zu tun?Wie starte ich git rebase --interaktiv in nicht-interaktiver Weise?

  1. Machen Sie git rebase --interactive, um einfach Standard-Boilerplate in eine Datei auszugeben, statt sie in eine Datei auszugeben und im Editor zu öffnen.
  2. Lassen Sie den Benutzer die Datei bearbeiten.
  3. Lassen Sie den Benutzer git rebase mit dem Namen der bearbeiteten Datei erneut ausführen.
  4. Fahren Sie mit dem üblichen Rebase-Verfahren fort.

Usecase: gescripted Rebasing natürlich. Siehe zum Beispiel how to re-order commits in Git non-interactively.

+0

Siehe http://stackoverflow.com/questions/12270357/really-flatten-a-git-merge für, wo dies auch nützlich wäre. – pfalcon

+0

Neben Git Rebase unten, git Filter-Zweig ist eine andere Option: http://StackOverflow.com/Questions/19636750/Git-Filter-Branch-MSG-Filter-To-reword-Apushed-Commit-Message – MarcH

Antwort

41

Nach einigem Nachdenken und Nachforschen stellte sich die Antwort als trivial heraus: git rebase -i nimmt den Editornamen von den bekannten EDITOR/VISUAL-Umgebungsvariablen, so dass das Überschreiben auf ein nicht interaktives Skript die Aufgabe erledigt.

EDITOR/VISUAL gilt jedoch gleichgültig für die Liste der Commits, Commit-Nachrichten beim Umformatieren und alles andere. Also gibt es seit http://git.kernel.org/?p=git/git.git;a=commit;h=821881d88d3012a64a52ece9a8c2571ca00c35cd eine spezielle Umgebungsvariable GIT_SEQUENCE_EDITOR, die nur für die Commit-Liste gilt.

das Rezept also neu zu bestellen oder Commits abflachen ist:

Run: GIT_SEQUENCE_EDITOR=<script> git rebase -i <params>. Ihr <script> sollte ein einzelnes Argument akzeptieren: den Pfad zu der Datei, die die standardmäßige Rebase-Commit-Liste enthält. Es sollte es an Ort und Stelle neu schreiben und beenden. Übliche Nachbearbeitungsvorgänge finden danach statt.

+0

nicht "GIT_SEQUENCE_EDITOR", scheint nützlich zu sein;) – c00kiemon5ter

+2

Oder, anstatt ein Skript für diesen einzigen Zweck zu erstellen, verwenden Sie einfach den vorhandenen Befehl 'true', der alle Argumente ignoriert und einen festen Rückkehrcode von '0' hat. –

+3

@me_and das hilft nur, wenn Sie eine 'Rebase -i' machen wollen, ohne die Commits tatsächlich neu zu ordnen. –

2

interaktive Modi ruft den Editor auf, mit dem gearbeitet werden soll.
der Editor in Gebrauch kann wie folgt erhalten werden:

git config --get core.editor 

Also, wenn Sie ein nicht-interaktives Editor eingestellt - das ist ein Editor, Befehle auf stdin akzeptiert, können Sie mit --interactive in einem nicht arbeiten -interactive weg :)
Ich weiß sicher vim akzeptiert Befehle, und so funktioniert der Standard-Editored, natürlich.

so, halten Sie den interaktiven Editor (wenn gewünscht)

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

stellen Sie den nicht-interaktiven Editor

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

und mit ihm arbeiten ..

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

und wiederherstellen der Editor (falls gewünscht)

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

Danke, wir haben wahrscheinlich angefangen, Antworten zu ähnlichen Zeiten zu schreiben, ich habe deine nicht gesehen, bevor ich meine gepostet habe ;-) – pfalcon

+0

Ich denke es ist einfacher EDITOR neu zu definieren, entweder pro Sitzung oder pro Befehl. – MarcH

+1

Ich würde stark davon abraten, 'git config --unset-all' zu machen oder was auch immer die Konfigurationsdatei des Benutzers in einem Skript ändern könnte. Um eine git config-Variable für einen Befehl festzulegen, verwenden Sie 'git -c var = val ', und in diesem Fall ist die Einstellung' EDITOR' viel einfacher. Es handelt sich um eine Umgebungsvariable, die sich nur auf den aktuellen Prozess bezieht, andere Prozesse nicht stört oder nichts auf die Festplatte schreibt. –

4

Hinzufügen zu @ pfalcon Antwort, Sie können sed als GIT_SEQUENCE_EDITOR verwenden.Zum Beispiel wollte ich jeden Commit bearbeiten, also tat ich dies:

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

ich dieses Skript verwenden (in fügen Sie es erlaubt begehen Splitting zu vereinfachen):

#!/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 

Fügen Sie einen Alias ​​zu Ihrem. gitconfig:

[alias] 
    autorebase = ! path_to_your_script 
5

auf Antwort des pfalcon Ausbau:

Lauf GIT_SEQUENCE_EDITOR=<script> git rebase -i <params>. <script> sollte einzelnes Argument akzeptieren - Pfad zur Datei, die die standardmäßige Rebase-Commit-Liste enthält. Das Skript sollte es an Ort und Stelle neu schreiben und beenden. Übliche Nachbearbeitungsvorgänge finden danach statt.

Wenn Sie eine Umgebungsvariable, die den Inhalt enthält, die Sie wollen:

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

catting eine Datei funktionieren würde:

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

Sie touch als Editor verwenden können, die berühren die Datei, so wird es geändert angezeigt. Zum Beispiel

GIT_SEQUENCE_EDITOR=touch git rebase -i [commit] 

es Aliasnamen, da baseline als Tag I gegen

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

rebase wollen Der Alias ​​arbeitet unter Windows, da die Shell es ausgeführt wird ist bash nicht cmd.

+0

Das funktioniert gut mit 'git --interactive --exec '. Ich setze ' 'auf einen Befehl, der die von meinem Zweig eingeführten oder modifizierten Tests ausführt, und' 'auf' master'. Das führt dazu, dass Git meine Tests gegen jedes Commit in der Verzweigung ausführt. – Mike

0

Basierend auf Jezz's answer, Ich habe ein Shell-Skript Agnostiker (GitReb) , die mit mehreren Argumenten Revisionen arbeitet, :/<text> Syntax, Wurzel begehen und tut auch einige Integritätsprüfungen.

Ich machte es einfacher und entfernt auch die t/split Aktion und delete ->drop Umwandlung die IMO aus diesem Skript des Oszilloskops sind.