2015-10-01 18 views
11

Sono in procinto di convertire un vecchio repository SVN a Git, che include il tentativo di ottenere tutti i rami/tag in tutti i posti giusti. Quella parte sta andando piuttosto bene, ma ci sono momenti in cui voglio aggiungere un commit nella storia nel mio script che in seguito voglio schiacciare con il prossimo commit. Il problema è che non sto afferrando i commit uno per uno, ma come un grande gruppo, quindi non posso schiacciarli mentre li estraggo dal repository SVN. Alla fine, il mio repository è simile al seguente:Squash due Git si commette nel mezzo della cronologia senza rebase interattivo

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

Voglio essere in grado di schiacciare commit 3 con SQUASH ME!, che è ovviamente facile con una rebase interattivo, ma più impegnativo all'interno di uno script. Il problema principale che mi sembra sia che mentre è facile fare il checkout a branch_1 oa qualsiasi commit prima, è difficile chiedere il commit al al e per me è difficile prevedere quanti commit tornano da branch_2 Ho bisogno di andare . Voglio davvero essere in grado di fare qualcosa del tipo:

git checkout branch_1+2 

Eventuali puntatori?

+0

Date un'occhiata alla "su" l'opzione per il comando rebase per fare le cose come schiacciamento, senza dover essere interattivo (ottimo per gli script): http: // blog .pivotal.io/labs/labs/git-rebase-on –

+0

@ Jonathan.Brink Non è esattamente quello che sto cercando. Questo post enfatizza la possibilità di abbandonare i commit. Voglio schiacciare (o riparare) il commit di "SQUASH ME!" Perché voglio le modifiche. Voglio solo che siano combinati con 'commit 3'. –

+0

Potrebbe essere più semplice lasciare che lo script agisca come editor durante il rebase interattivo. – coredump

risposta

8

cosa si sta parlando di non è un zucca, ma una correzione , perché la zucca vi chiederà per il commit msg in modo interattivo, mentre la correzione utilizza il messaggio di commit dalla testa commit.

Ecco uno script che lo fa senza intervento.

Lo script: /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" 

utilizzarlo con

git fixup <commit-id> 

Ad esempio, se la vostra storia è:

ce0e2fd (master, HEAD) commit 4 
72ab3c4 commit 3 
8150939 commit 2 
301c1e1 commit 1 

Si può fare git fixup 72ab3c4 che si fondono insieme "commit 3 "e" commit 2 "come commit con il messaggio" commit 2 "e pl ritorna sul ramo principale.

+0

Suggerirei di aggiungere 'set -e' per abortire quando la directory di lavoro è sporca. Il primo 'git checkout' si lamenterà e l'intero script uscirà. – coredump

+0

Grazie per il consiglio, ho messo quello – edi9999

5

Da git rebase --help:

--autosquash

Quando il messaggio di log commit comincia con (o "correzione ...!"), E non v'è "squash ...!" un commit il cui titolo inizia con lo stesso ..., modifica automaticamente l'elenco di rebase -i in modo che il commit segnato per lo schiacciamento arrivi subito dopo che il commit è stato modificato e modifica l'azione del commit spostato dal pick schiacciare (o aggiustare).

Questa opzione è valida solo se si utilizza l'opzione interattiva.

Sembra che farà la metà di ciò che si desidera, se l'input è nella forma corretta.

L'altra metà impedisce l'avvio dell'editor interattivo.Fortunatamente, l'editor è configurabile, quindi possiamo semplicemente impostarlo su qualcosa di innocuo.

Prova questo:

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

Impostare l'editor di true (uno strumento che esce semplicemente con successo) è sufficiente per convincere git per procedere con l'impostazione predefinita rebase impostazioni, che l'auto-zucca avrebbe dovuto fissare a qualcosa utile.


In alternativa, se --autosquash non fa ciò che si vuole, è possibile impostare EDITOR a qualsiasi script che ti piace:

env EDITOR=mysquasher.sh git rebase -i <from-here> 

Lo script può fare tutto il necessario, ma nel tuo caso è necessario trovare solo ogni riga contenente "SQUASHME!" e modificare "pick" nella riga seguente per leggere "fixup". Questo probabilmente può essere raggiunto più facilmente con 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" 
+0

env EDITOR = true tira ancora l'editor per me. – Andrew

+0

Avete impostato 'VISUAL' o altre variabili di ambiente sospette? – ams

+0

non che io possa dire. – Andrew

Problemi correlati