Può "git pull" nascondere e visualizzare automaticamente le modifiche in sospeso?


122

So come risolverlo:

user@host$ git pull
Updating 9386059..6e3ffde
error: Your local changes to the following files would be overwritten by merge:
    foo.bar
Please, commit your changes or stash them before you can merge.
Aborting

Ma non c'è un modo per far git pullfare il stashe popdanza per me?

Se questo comando ha un nome diverso, va bene.

La creazione di un alias di shell per git stash; git pull; git stash popè una soluzione, ma cerco una soluzione migliore.


che ne dici di un alias git ?
Яois

20
L'esecuzione a livello di git stash; git pull; git stash popprogrammazione è pericolosa, perché se non c'è nulla da mettere da parte, git stashnon sarà un'operazione, ma git stash popfarà apparire l'ultima scorta (se presente), che quasi certamente non è quello che vuoi. L'utente torek ha un ottimo post su questo argomento su Stack Overflow, ma non riesco a trovarlo ...
jub0bs


1
@ guettli Non stavo insinuando che la tua domanda fosse un duplicato, stavo solo rispondendo al commento di Jubobs.
VonC

2
Inoltre, l'operazione dovrebbe riuscire solo se la scorta può essere applicata in modo pulito dopo il tiro. In caso di conflitti, l'intera operazione fallisce atomicamente in modo che l'albero non venga modificato. Questo è quello che vorrei fare: o tirare giù le modifiche con quelle locali unite, oppure fallire con un errore e lasciarmi decidere manualmente cosa fare dopo. È possibile questo tipo di "transazione" git?
Ed Avis

Risposte:


185

Per Git 2.6+ (rilasciato il 28 settembre 2015)

Il solo git config l'impostazione che potrebbe interessare è:

rebase.autoStash

(con Git 2.27, Q2 2020, ora hai anche merge.autostash, vedi sotto)

Se impostato su true, crea automaticamente una scorta temporanea prima dell'inizio dell'operazione e applicala al termine dell'operazione.
Ciò significa che puoi eseguire rebase su un albero di lavoro sporco.

Tuttavia, usatela con attenzione: l'applicazione stash finale dopo un rebase riuscito potrebbe provocare conflitti non banali. Il valore predefinito è false.

combinalo con:

pull.rebase

Quando è vero, riassegna i rami sopra il ramo recuperato, invece di unire il ramo predefinito dal telecomando predefinito quando viene eseguito "git pull".

git config pull.rebase true
git config rebase.autoStash true

Sarebbe sufficiente per un semplice git pulllavorare anche su un albero sporco.
In questo caso non è necessario alcun alias.


Vedere commit 53c76dc (04 luglio 2015) di Kevin Daudt ( Ikke) .
(Fuso da Junio ​​C Hamano - gitster- in commit e69b408 , 17 agosto 2015)

pull: consenti albero sporco quando rebase.autostashabilitato

rebase ha imparato a nascondere le modifiche quando incontra un albero di lavoro sporco, ma git pull --rebasenon lo fa.

Verificare solo se l'albero di lavoro è sporco quando rebase.autostashnon è abilitato.


Nota: se vuoi tirare senza autostash (anche se rebase.autoStash trueè impostato), hai da git 2.9 (giugno 2016):

 pull --rebase --no-autostash

Vedere commit 450dd1d , commit 1662297 , commit 44a59ff , commit 5c82bcd , commit 6ddc97c , commit eff960b , commit efa195d (2 aprile 2016) e commit f66398e , commit c48d73b (21 marzo 2016) di Mehul Jain ( mehul2029) .
(Fuso da Junio ​​C Hamano - gitster- in commit 7c137bb , 13 aprile 2016)

Commit f66398e in particolare include:

pull --rebase: aggiungi --[no-]autostashbandiera

Se la rebase.autoStashvariabile di configurazione è impostata, non è possibile sovrascriverla per " git pull --rebase" dalla riga di comando.

Insegna " git pull --rebase" il --[no-]autostashflag della riga di comando che sovrascrive il valore corrente di rebase.autoStash, se impostato. Poiché " git rebase" comprende l' --[no-]autostashopzione, è solo questione di passare l'opzione al sottostante " git rebase" quando " git pull --rebase" viene chiamato.


Avvertenza: prima di Git 2.14 (Q3 2017), " git pull --rebase --autostash" non si auto-memorizzava quando la cronologia locale avanza rapidamente all'upstream.

Vedi commit f15e7cf (01 giugno 2017) di Tyler Brazier ( tylerbrazier) .
(Fuso da Junio ​​C Hamano - gitster- in commit 35898ea , 05 giugno 2017)

pull: ff --rebase --autostashfunziona in dirty repo

Quando git pull --rebase --autostashin un repository sporco si verificava un avanzamento rapido, non veniva eseguito il backup automatico di nulla e il pull non riusciva.
Ciò era dovuto a una scorciatoia per evitare di eseguire rebase quando possiamo avanzare rapidamente, ma l'autashash viene ignorato su quel codepath.


Aggiornamento: Mariusz Pawelski pone nei commenti una domanda interessante:

Quindi tutti scrivono di autostashquando fai rebase (o pull --rebase).

Ma nessuno si prende cura del flash automatico quando esegui il pull normale con le unioni .
Quindi non esiste un interruttore automatico per questo? O mi manca qualcosa? Preferisco farlo, git pull --rebasema OP ha chiesto del git pull " standard "

Risposta:

Il thread originale che discuteva di questa funzione di autostash, era stato implementato originariamente sia per git pull(merge) che per git pull --rebase.

Ma ... Junio ​​C Hamano (manutentore di Git) ha notato che:

Se pull-mergefosse qualcosa che inducesse il "fastidio" che ha innescato questo argomento, per definizione, la modifica locale si sovrappone all'unione e questo "stash pop" interno toccherà i percorsi toccati dalla fusione e probabilmente non risulterà "Dropped "ma lascia da risolvere ulteriori conflitti.

Sospetto che la pull.autostashconfigurazione non sia una buona aggiunta perché incoraggia un flusso di lavoro pessimo e doloroso.
In casi semplici potrebbe non far male, ma quando i cambiamenti locali sono complessi, sarebbe attivamente dannoso che non averli e la configurazione deruba l'incentivo a scegliere.

L'equazione è alquanto diversa per "pull-rebase", poiché "rebase" insiste per iniziare da un albero funzionante pulito, quindi il fastidio "scarica e poi interrompi" sembra più grande. Ho il sospetto che l'allentamento possa essere una soluzione più produttiva al problema reale.

Quindi, per quanto riguarda un classico pull-merge, è meglio:

incoraggiare l'utente a pensare alla natura del WIP che ha nell'albero di lavoro prima di eseguire " git pull" .
È una bestia troppo complessa che potrebbe interferire con ciò che stanno facendo gli altri, o è un cambiamento banale che può nasconderlo e tirarlo indietro?

Nel primo caso, starà molto meglio facendo " checkout -b", continua a lavorare finché il cambiamento locale non assume una forma un po 'migliore e "si impegna", prima di passare al ramo originale.

In quest'ultimo caso, è meglio che faccia:

  • " git pull",
  • dopo aver scoperto che è in conflitto, esegui
    • git stash,
    • git merge FETCH_HEAD e
    • git stash pop

Detto questo, con Git 2.27 (Q2 2020), " git pull" ha imparato ad avvertire quando non pull.rebaseesiste alcuna configurazione e né --[no-]rebase--ff-onlyviene fornito (il che risulterebbe un'unione).

Vedi commit d18c950 (10 marzo 2020) di Alex Henrie ( alexhenrie) .
(Fuso da Junio ​​C Hamano - gitster- nel commit 1c56d6f , 27 marzo 2020)

pull: avvisa se l'utente non ha detto se rebase o unire

Firmato da: Alex Henrie

Spesso gli utenti inesperti di Git dimenticano di dire " pull --rebase" e si ritrovano con un'unione non necessaria dall'upstream.

Quello che di solito vogliono è " pull --rebase" nei casi più semplici, o " pull --ff-only" aggiornare la copia dei principali rami di integrazione e ribasare il loro lavoro separatamente.
La pull.rebasevariabile di configurazione esiste per aiutarli nei casi più semplici, ma non esiste alcun meccanismo per renderlo consapevole di questi utenti.

Emette un messaggio di avviso quando non viene fornita alcuna --[no-]rebaseopzione dalla riga di comando e nessuna pull.rebasevariabile di configurazione.
Ciò arrecherà fastidio a coloro che non vogliono " pull --rebase", che non hanno dovuto fare nulla di speciale, ma il costo dell'inconveniente viene pagato una sola volta per utente, il che dovrebbe essere un costo ragionevole per aiutare un numero di nuovi utenti.


Con Git 2.27 (Q2 2020), " git merge" apprende l' --autostashopzione " " e la nuova merge.autostashimpostazione.

Vedere commettere d9f15d3 , commettere f8a1785 , commettere a03b555 , commettere 804fe31 , commettere 12b6e13 , commettere 0dd562e , commettere 0816f1d , commettere 9bb3dea , commettere 4d4bc15 , commettere b309a97 , commettere f213f06 , commettere 86ed00a , commettere facca7f , commettere be1bb60 , commettere efcf6cf , commettere c20de8b , commettono bfa50c2 , commit 3442c3d , commit 5b2f6d9 (07 aprile 2020), commit 65c425a(04 apr 2020) e commit fd6852c , commit 805d9ea (21 mar 2020) di Denton Liu ( Denton-L) .
(Fusione di Junio ​​C Hamano - gitster- in commit bf10200 , 29 aprile 2020)

pull: passa --autostash per unire

Firmato da: Denton Liu

Prima, --autostashlavorava solo con git pull --rebase.

Tuttavia, nell'ultima patch, anche l'unione appresa --autostash, quindi non c'è motivo per cui dovremmo più avere questa restrizione.
Insegna a tirare per passare --autostasha unire, proprio come ha fatto per il rebase.

E:

rebase: usa apply_autostash()da sequencer.c

Firmato da: Denton Liu

La apply_autostash()funzione in builtin/rebase.cè abbastanza simile alla apply_autostash()funzione in sequencer.cquanto sono quasi intercambiabili, tranne per il tipo di arg che accettano. Rendi la sequencer.cversione extern e usala in rebase.

La versione rebase è stato introdotto nel 6defce2b02 ( "rebase integrato: supporto --autostashopzione", 2018/09/04, Git v2.20.0-RC0 - merge elencati nel lotto # 8 ) nell'ambito del guscio alla conversione C.
Ha scelto di duplicare la funzione perché, all'epoca, c'era un altro progetto in corso che converte anche il rebase interattivo da shell a C e non volevano scontrarsi con loro refactoring della sequencer.cversione di apply_autostash().
Poiché entrambi gli sforzi sono fatti da tempo, ora possiamo combinarli liberamente.


A partire dalla 2.4.2, questo non è ancora implementato. Forse un giorno. rebase.autoStashsi applica solo quando si utilizza rebase. pull.rebasesi applica solo quando si utilizza pull.
Randal Schwartz

"Sarebbe sufficiente perché un semplice git pull funzioni anche su un albero sporco." Come ha commentato Randal, questo non è ancora vero. Il pull.c del master attuale sceglie ancora di farlo die_on_unclean_work_tree.
Pradhan

1
@Pradhan sono d'accordo. L'implementazione è appena stata masterizzata questa mattina e dovrebbe essere disponibile per git 2.6. Ho modificato la risposta per renderlo chiaro.
VonC

Ho confermato che autostash funziona con git 2.5.5.
Joshua Hoblitt

1
Quindi tutti scrivono di autostash quando fai rebase(o pull --rebase). Ma nessuno si prende cura del lampeggio automatico quando fai normalmente le pullfusioni. Quindi non esiste un interruttore automatico per questo? O mi manca qualcosa? Preferisco farlo, git pull --rebasema OP ha chiesto di "standard"git pull
Mariusz Pawelski

41

Per risparmiare qualche secondo per gli esploratori in arrivo, ecco un riepilogo (grazie a @VonC):

git pull --rebase --autostash

6
Il punto è: dopo un git config pull.rebase truee git config rebase.autoStash true, tutto ciò di cui avrai bisogno è git pull. Solo git pull. Non sono necessarie altre opzioni.
VonC

3
Sembra che tu abbia bisogno almeno di Git 2.9 per l' --autostashopzione. L' -c rebase.autoStash=truelavora in Git 2.6 in poi.
ntc2

15

Come affermato nel commento sopra, l'impostazione dei due valori di configurazione attualmente non funziona git pull, poiché la configurazione di autostash si applica solo ai rebase effettivi. Questi comandi git fanno quello che vuoi:

git fetch
git rebase --autostash FETCH_HEAD

Oppure impostalo come alias:

git config alias.pullr '!git fetch; git rebase --autostash FETCH_HEAD'

Quindi fa:

git pullr

Naturalmente, questo alias può essere rinominato come desiderato.


7

Con Git 2.6+ puoi usare quanto segue:

alias gup='git -c rebase.autoStash=true pull --rebase'

Questo --rebasefa sì che git-pull usi rebaseinvece di merge, quindi impostazioni / opzioni come --ff-onlynon verranno applicate.

Sto usando un alias con cui eseguire il pull --ff-onlyper impostazione predefinita ( git pull --ff-only), e posso quindi utilizzare gup(dall'alto) nel caso in cui un'unione in avanti veloce non sia possibile o ci siano modifiche nascoste.


Qual'è la differenza principale tra git pull --ff-onlyegit pull pull --rebase --autostash
alper

0

Come hai già detto, questo è il modo per farlo. Puoi usarlo in alias per salvarti dalla digitazione e usare il collegamento oppure puoi usarlo in una singola riga (può anche essere un alias)

git stash && git pull --rebase && git stash pop

Farà la stessa cosa che hai fatto ma in una singola riga (&&) e se imposti come alias sarà anche più breve.

Le seguenti righe visualizzeranno le modifiche in entrata / in uscita prima di tirare / spingere

git log ^master origin/master
git log master ^origin/master

8
Questo approccio non è sicuro: se non c'è niente da mettere da parte, il primo comando non farà nulla, quindi stash poprimuoverà alcune cose casuali da prima.
John Zwinck

Giusto per essere più chiari: anche se git stashnon nasconde nulla, "non restituisce" nessun codice di errore, quindi && continuerà comunque con git pulle git stash pope aprirà una scorta precedente. Quindi è meglio non usarlo a meno che tu non sia molto sicuro che nasconderà qualcosa!
MoonLite
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.