2010-10-30 6 views
12

Sono assolutamente amare git add -p e git stash ma di tanto in tanto il seguente problema, che viene riprodotta con la seguente sequenza di comandi:git Stash e modificati Hunk

  • git add -p my_file: poi ho modificare un pezzo manualmente (usando e) a causa della scissione che git suggerisce non soddisfa me
  • git stash --keep-index: poi faccio qualche test, e se i test passano non commetto
  • git stash pop: ora il problema si verifica: il file my_fileora è considerato come in conflitto, e git ha completamente pasticciato con il mio pezzo modificato, quindi devo modificare il file, rimuovere i segni di unione inutili ed eseguire git add my_file seguito da git reset HEAD

Sono perplesso perché questo accade solo quando si modifica manualmente un blocco. Non vedo come questo dovrebbe fare alcuna differenza.


per riprodurre il problema:

  • touch newfile
  • git add newfile
  • git commit -m 'newfile'
  • aggiungere due righe nel file
  • git add -p newfile
  • modificare l'h unk (e), rimuovere una delle linee del pezzo, quindi chiudere git add (q)
  • git stash --keep-index
  • git stash pop

Ora il file newfile è in stato unmerged. Notare, ancora una volta, che il problema si verifica solo con gli hunk modificati manualmente. Non c'è nessun problema con i comandi sopra se non si modifica manualmente alcun pezzo.

Per inciso, lo stato precedente del file si trova nella terza fase (git show :3:newfile) e la versione precedente in staging si trova nella seconda fase (git show :2:newfile). Quindi, con un po 'di magia nera, sono riuscito a mettere la seconda fase in questo indice, e il terzo stadio nel repository di lavoro ... ma non so come farlo, così lo faccio a mano. :-(

+0

Ho provato più volte, ma non riesco a riprodurre il problema con git versione 1.7.2.3. Che versione stai usando? –

+0

Sto usando la versione 1.7.3.1 su Mac OS X. –

+1

Provato di nuovo con diverse modifiche casuali in 'git add -p' - e funziona sempre bene per me. A proposito, sono su Linux. Sembra un bug - ti consiglierei di chiedere sulla mailing list git, sono abbastanza reattivi. –

risposta

4

Ho posto la domanda nella mailing list di Git. Quello che descrivo è il comportamento previsto, non è un bug.:-(

Ecco la risposta che ho ricevuto:

Se non si modifica il pezzo manualmente, ogni pezzo sarà o in HEAD stato o nello Stato A, e applicando il diff tra testa e a tale file sarà o un no-op (pezzo già applicato), o un'applicazione di successo .

per me questa è una grave limitazione della git add --patch, e non capisco in che modo questo il comportamento può essere utile a chiunque, ma imparerò a farlo convivici.

+1

Sembra che il problema è che quando si esegue "git stash --keep-index", esso memorizza sia le modifiche staged che quelle non modificate, con la sola differenza che preserva le modifiche graduali nella copia di lavoro. E quando provate ad applicare lo stash, le modifiche graduali sono entrambe nella copia di lavoro e nello stash che causano un conflitto. Nel caso di hunk non modificati durante la risposta, ricorda quali hunk sono presenti nella copia di lavoro e quali non sono e non si applica ai conflitti di fusione evitati una volta presenti. Per un pezzo modificato, solo una parte di esso applicata non può fare il trucco. – axk

2

git stash --keep-index conserva l'indice, ma aggiunge ancora il contenuto dell'indice come parte della scorta

Prova git stash save -p -. Un po 'più noiosa per salvare la scorta, ma probabilmente fare quello che vuoi.

+0

Come spiega che git ritiene che ci sia un conflitto ** solo ** quando ho un blocco modificato manualmente? –

+0

Poiché gli indici non corrispondono quando si gira la posta indesiderata. – Scott

+0

@Scott: scusa, non capisco la tua risposta ...: -/perché c'è un conflitto solo quando c'era un blocco modificato manualmente? –

7

Per creare e testare un indice contenente parte dei lavoro modifiche degli alberi, tra cui grossi pezzi modificati manualmente, effettuare:

git add --patch <files> 

git stash --keep-index 

<test the indexed changes> 

git reset --hard 

git stash pop --index 

A questo punto non vi siano conflitti, e il repository, l'indice e directory di lavoro sono nello stato immediatamente precedente allo git stash. È ora possibile git commit le modifiche indicizzate.

Naturalmente, questo è piuttosto strano e non molto intuitivo e mi piacerebbe davvero sapere se c'è un modo più semplice per farlo.

+0

+1, funziona. Sono arrivato alla stessa soluzione ma ho perso l'opzione --index. Questo è un modo logico di fare le cose considerando che esso memorizza sia l'indice che le modifiche non modificate in modo da evitare il conflitto di fusione tra le modifiche di staged nella copia di lavoro e quelle nascoste si deve prima rimuovere quelli dalla copia di lavoro (cioè fare un hard reset). – axk

+0

Grazie! Ora per farlo agganciare a Magit ... – seanmcl