2011-10-13 19 views
292

Come asked in this question, voglio anche sapere come risolvere uno git stash pop in conflitto senza aggiungere tutte le modifiche a un commit (proprio come "git stash pop" senza conflitti).Come risolvere il conflitto di git stash senza commit?

Il mio approccio attuale è molto uncool perché lo faccio in questo modo:

git stash pop -> CONFLICT 
git stash drop 
[resolve conflict] 
[add conflict files] 
git reset HEAD <all files that are in commit-mode> 

[Update] Un modo di riprodurlo:

mkdir foo; cd foo; git init 
echo "1" > one 
echo "2" > two 
git add -A; git commit -m "first" 
echo "1.1" > one 
echo "2.1" > two 
git stash 
echo "2.2" > two 
git commit -a -m "second" 
echo "Only this file would stay in HEAD without the conflict" > third 
git add third 
git stash pop 
git status 

2016-06-27: Aggiunto un nuovo file chiamato "terzo" all'esempio per mostrare che soluzioni alternative come la soluzione di scy funzionano solo per HEAD vuoti ma non risolvono il problema iniziale che l'HEAD non ha lo stesso contenuto come per uno git stash pop senza conflitto.

+0

Così si 'git add' i file conflitto risolto, lasciando loro messa in scena nell'indice, e che ci si vuole non averli nel nostro indice ? – Romain

+0

Sì, è giusto. Voglio solo il comportamento che 'git stash pop' ha quando non si verifica alcun conflitto (ma con la notifica che i file devono essere uniti). – Sven

+2

Sembra che la risposta per questo è qui: http://stackoverflow.com/questions/3945826/git-stash-questions. Nella risposta scelta, al 4 ° commento, Adam spiega perché git fa questo. – Patrick

risposta

72

Invece di aggiungere le modifiche apportate per risolvere il conflitto, è possibile utilizzare git reset HEAD file per risolvere il conflitto senza organizzare le modifiche.

Potrebbe essere necessario eseguire questo comando due volte, tuttavia. Una volta per contrassegnare il conflitto come risolto e una volta per rimuovere le modifiche apportate dalla routine di risoluzione dei conflitti.

È possibile che ci sia una modalità di ripristino che fa entrambe le cose contemporaneamente, anche se non ce n'è una adesso.

+2

La modalità di ripristino è quello che cerco - altre soluzioni sono come quella che ho descritto e non pratico per più di 5 File. – Sven

+19

E usare "git stash drop" in seguito per finire il "git stash pop". – DavidLiu

+2

Anche se la questione non chiede esplicitamente, potrebbe essere utile per aggiornare la risposta a includere "git goccia scorta", come la scorta non è caduto automaticamente nel caso di un conflitto. –

4

Sembra che questa potrebbe essere la risposta che stai cercando, non l'ho ancora provato personalmente, ma sembra che possa fare il trucco. Con questo comando GIT proverà ad applicare le modifiche come erano prima, senza provare ad aggiungerle tutte per il commit.

git stash apply --index

Ecco la spiegazione completa:

http://git-scm.com/book/en/Git-Tools-Stashing

+0

Grazie per questo suggerimento, ma questo non aiuterà quando ho già fatto 'git scorta pop' - o c'è un modo per ripristinare questo e per fare' git scorta applicare --index' quando ho scoperto che 'git stash pop' si imbatterà in un conflitto? – Sven

+0

Ho aggiunto un esempio su come produrre questo - immagina di modificare più di 10 file, quindi non sai quale di essi hai modificato al di fuori della scorta. – Sven

+3

Se si guarda in fondo a questo post [QUI] (http://stackoverflow.com/questions/2840816/git-stash-blunder-git-stash-pop-and-ended-up-with-merge-conflicts) si dice che se si esegue 'git scorta pop' e finisce con i conflitti, la scorta non vengono rimossi ... in modo da poter eseguire' git ripristinare --hard' per annullare il pop e quindi provare la soluzione che ho suggerito. –

223

Supponiamo di avere questo scenario in cui si conserva le modifiche al fine di tirare di origine. Forse perché le modifiche locali sono solo debug: true in alcuni file di impostazioni. Ora tiri e qualcuno ha introdotto una nuova impostazione lì, creando un conflitto.

git status dice:

# On branch master 
# Unmerged paths: 
# (use "git reset HEAD <file>..." to unstage) 
# (use "git add/rm <file>..." as appropriate to mark resolution) 
# 
# both modified:  src/js/globals.tpl.js 
no changes added to commit (use "git add" and/or "git commit -a") 

Va bene. Ho deciso di andare con quello che Git ha suggerito: ho risolto il conflitto e impegnata:

vim src/js/globals.tpl.js 
# type type type … 
git commit -a -m WIP # (short for "work in progress") 

Ora la mia copia di lavoro si trova nello stato che voglio, ma ho creato un commit che io non voglio avere. Come faccio a liberarmi di quel commit senza modificare la mia copia di lavoro? Aspetta, c'è un comando popolare per questo!

git reset HEAD^ 

La mia copia di lavoro non è stata modificata, ma il commit WIP è sparito. Questo è esattamente quello che volevo! (Nota che non sto usando --soft qui, perché se ci sono file auto-uniti nella tua scorta, sono auto-organizzati e quindi si finirebbe con questi file di essere messi in scena di nuovo dopo reset.)

Ma c'è ancora una cosa di sinistra: La pagina man per git stash pop ci ricorda che "Applicare lo Stato può fallire i conflitti, in questo caso, non viene rimosso dalla lista scorta È necessario risolvere i conflitti di. mano e chiamare il numero git stash drop manualmente in seguito. " Ecco, questo è esattamente quello che facciamo oggi:

git stash drop 

e fatto.

+3

Anche questo ha funzionato per un 'git stash apply 'per me, grazie. – 2rs2ts

+24

C'è solo molta bruttezza ereditaria nel dover deliberatamente eseguire il commit reset HEAD^... per qualcosa che dovrebbe influenzare solo l'albero di lavoro. – nus

+3

Perché non risolvere i conflitti e quindi 'git add: ' seguito da 'git reset HEAD'? – BoltzmannBrain

2

git stash branch opere saranno, che crea un nuovo ramo per voi, estrae il commit eri quando si nascosto il vostro lavoro, il vostro lavoro riapplica lì, e poi scende la scorta se si applica con successo. controllo this

9
git checkout stash -- . 

ha funzionato per me.

Nota: questo può essere pericoloso, in quanto non cerca di unire le modifiche dal scorta nella vostra copia di lavoro, ma sovrascrive con i file nascosto invece. Quindi puoi perdere le tue modifiche senza commit.

+1

Direi che questo ** sovrascrive ** i file in copia di lavoro con i file dalla scorta. Quindi perderai tutte le tue modifiche non impegnate. Quindi non c'è motivo di fare 'git stash pop' prima (che sta provando a ** unire ** i file nascosti nella tua copia di lavoro). Se stai bene, puoi usare 'git checkout stash - .' invece di' git stash pop'. –

+2

-1 SOVRASCRIVE le modifiche ai file correnti. Voglio dire se è quello che vuoi, allora bene, ma probabilmente la maggior parte delle volte non vorresti quello. – phoenix

165

Non penso che fare un commit e quindi resettare il ramo per rimuovere quel commit e soluzioni alternative simili suggerite in altre risposte sono il modo pulito per risolvere questo problema.

seguente soluzione sembra essere molto più pulito per me ed è anche suggerito dal Git sé - eseguire git status nel repository con un conflitto:

Unmerged paths: 
    (use "git reset HEAD <file>..." to unstage) 
    (use "git add <file>..." to mark resolution) 

Facciamo quello che Git suggerisce senza fare alcun impegno:

  1. Manualmente (o utilizzando uno strumento di unione GUI) risolvere i conflitti.
  2. Utilizzare git reset per contrassegnare i conflitti come risolti e rimuovere le modifiche. Puoi eseguirlo senza parametri e Git rimuoverà tutto dall'indice. Non è necessario eseguire git add prima.
  3. Infine, rimuovere lo stash con git stash drop, perché Git non lo fa in caso di conflitto.

Quindi:

$ git stash pop 

# ...manually resolve conflict(s) 

$ git reset 

$ git stash drop 

Nota: aggiunta di file per l'indice dopo un conflitto è stato risolto è di proposito. In questo modo puoi differenziare le modifiche dalla scorta precedente e le modifiche apportate dopo la risoluzione del conflitto. Se non ti piace, puoi sempre usare git reset per rimuovere tutto dall'indice.

Un'altra nota: Si consiglia vivamente di utilizzare uno degli strumenti di unione a 3 vie per risolvere i conflitti, ad es. KDiff3. Solitamente risolve automaticamente la maggior parte dei conflitti stessi.

+3

Ho trovato questo più naturale della risposta accettata. Funziona anche con 'git stash apply'. – Benjamin

+0

'git stash drop' non è necessario quando si esegue' git stash pop' –

+15

@kamalpal sembra essere necessario quando 'git stash pop' fallisce con i conflitti. –

1

Secondo git stash questions, dopo aver risolto il conflitto, git add <file> è la giusta linea di condotta.

E 'stato dopo aver letto this comment che ho capito che le modifiche vengono automaticamente aggiunti all'indice (in base alla progettazione). Ecco perché git add <file> completa la procedura di risoluzione dei conflitti.

2

Il modo più veloce che ho trovato è quello di risolvere il conflitto, quindi fare git add -u e quindi fare git reset HEAD, che non coinvolge nemmeno un commit.

-1
git add . 
git reset 

git add . metterà in scena tutte le file dicendo git che avete risolto il conflitto

git reset saranno unstage TUTTI i file messi in scena senza creare un commit

+0

Questa non è una cattiva risposta, è praticamente come 'git add -u' quindi' git reset' – ebob

0

non è il modo migliore per farlo, ma funziona:

$ git stash apply 
$ >> resolve your conflict << 
$ >> do what you want to do with your code << 
$ git checkout HEAD -- file/path/to/your/file