2012-09-12 16 views
31

È possibile seguire?Come posso eseguire git rebase - interattivo in modo non interattivo?

  1. Fare git rebase --interactive ad appena uscita boilerplate standard per un file, invece l'output su un file e aprirlo in editor.
  2. Consenti all'utente di modificare il file.
  3. Consentire all'utente di eseguire nuovamente git rebase con il nome del file modificato.
  4. Proseguire con la normale procedura di rebase.

Caso di utilizzo: rebasing programmato, ovviamente. Vedere how to re-order commits in Git non-interactively per esempio.

+0

Vedere http://stackoverflow.com/questions/12270357/really-flatten-a-git-merge per dove questo sarebbe utile, anche. – pfalcon

+0

Oltre a git rebase di seguito, git filter-branch è un'altra opzione: http://stackoverflow.com/questions/19636750/git-filter-branch-msg-filter-to-reword-a-pushed-commit-message – MarcH

risposta

41

Dopo un po 'di riflessione e di ricerca, la risposta è risultata banale: git rebase -i prende il nome dell'editor dalle ben note variabili d'ambiente EDITOR/VISUAL, quindi ignorare che fare riferimento a uno script non interattivo fa il lavoro.

Tuttavia, EDITOR/VISUAL si applica indifferentemente all'elenco di commit, ai messaggi di commit durante la riformulazione e qualsiasi altra cosa. Pertanto, dal http://git.kernel.org/?p=git/git.git;a=commit;h=821881d88d3012a64a52ece9a8c2571ca00c35cd, esiste una variabile di ambiente speciale GIT_SEQUENCE_EDITOR che si applica solo all'elenco di commit.

Quindi, la ricetta di ri-ordine o appiattire commit è:

Run: GIT_SEQUENCE_EDITOR=<script> git rebase -i <params>. Il tuo <script> dovrebbe accettare un singolo argomento: il percorso del file contenente l'elenco di commit standard di rebase. Dovrebbe riscriverlo sul posto ed uscire. L'elaborazione abituale di rebase avviene successivamente.

+0

non conoscere 'GIT_SEQUENCE_EDITOR', sembra utile;) – c00kiemon5ter

+2

Oppure, invece di creare uno script per questo solo scopo, basta usare il comando esistente' true', che ignora qualsiasi argomento e ha un codice di ritorno fisso di '0'. –

+3

@me_e questo aiuta solo se si desidera eseguire un 'rebase -i' senza effettivamente riordinare i commit. –

2

le modalità interattive richiamano l'editor di insiemi con cui lavorare.
l'editor in uso può essere recuperato con:

git config --get core.editor 

Quindi, se si imposta un editor non interattivo - che è un editor che accetta comandi su standard input, è possibile lavorare con --interactive in una non -interattivo modo :)
Io so per certo vim accetta comandi, e così fa l'editor standarded, ofcourse.

così, tenere l'editor interattivo (se voluto)

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

impostare l'editor non interattivo

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

e funzionano con esso ..

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

e il ripristino l'editor (se desiderato)

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

Grazie, probabilmente abbiamo iniziato a scrivere risposte allo stesso tempo, non ho visto il tuo prima di pubblicare il mio ;-) – pfalcon

+0

Penso che sia più semplice ridefinire EDITOR, sia per sessione che per comando. – MarcH

+1

Sconsiglio vivamente di fare 'git config --unset-all' o qualunque cosa possa modificare il file di configurazione dell'utente in uno script. Per impostare una variabile git config per un comando, usa 'git -c var = val', e in questo caso l'impostazione' EDITOR' è molto più semplice. È una variabile di ambiente, quindi si applica solo al processo corrente, non disturberà altri processi né scriverà nulla sul disco. –

4

Aggiunta alla risposta di @ pfalcon, è possibile utilizzare sed come GIT_SEQUENCE_EDITOR.Per esempio, ho voluto modificare ogni commit, così ho fatto questo:

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

Io uso questo script (in aggiungerlo permette di semplificare commettere splitting):

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

aggiungere un alias al vostro. gitconfig:

[alias] 
    autorebase = ! path_to_your_script 
5

Ampliando la risposta di pfalcon:

Esegui GIT_SEQUENCE_EDITOR=<script> git rebase -i <params>. <script> dovrebbe accettare un singolo argomento: percorso del file contenente l'elenco di commit standard di rebase. Lo script dovrebbe riscriverlo sul posto ed uscire. L'elaborazione abituale di rebase avviene successivamente.

Se si dispone di una variabile di ambiente che contiene il contenuto che si desidera:

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

catting un file potrebbe funzionare troppo:

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

È possibile utilizzare touch come l'editor, che toccherà il file in modo che appaia modificato. Per esempio

GIT_SEQUENCE_EDITOR=touch git rebase -i [commit] 

a Alias ​​che, data baseline come un tag voglio rebase contro

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

L'alias funziona sotto Windows, perché il guscio è in esecuzione non è bashcmd.

+0

Funziona bene con 'git --interactive --exec '. Ho impostato '' su un comando che esegue i test introdotti o modificati dal mio ramo, e '' su 'master'. Ciò fa sì che git esegua i miei test contro ogni commit nel ramo. – Mike

0

Sulla base di Jezz's answer, ho fatto uno script di shell-agnostico (GitReb) che lavora con le revisioni multiple-argomento, :/<text> sintassi, radice di commit e fa anche alcuni controlli di integrità.

ho anche reso più semplice e rimosso l'azione t/split e delete ->drop conversione che sono IMO fuori del campo di applicazione di questo script.

Problemi correlati