Qual è il vantaggio del processo di commit in due fasi (staging) di git?


175

Sto imparando git e ho notato che ha un processo di commit in due passaggi:

  1. git add <files>
  2. git commit

Il primo passo posiziona le revisioni in quella che viene chiamata "area di gestione temporanea" o "indice".

Ciò che mi interessa è il motivo per cui viene presa questa decisione di progettazione e quali sono i suoi vantaggi?

Inoltre, come utente git fai questo o semplicemente usi git commit -a?

Lo chiedo perché vengo da bzr (Bazaar) che non ha questa funzione.


3
+1 per chiedere. Uso Tortoise SVN, che ha lo stesso approccio e non ho mai capito il perché.
DPD,

3
L'area di stadiazione non è così insolita. L'equivalente, ad esempio, in TFS sarebbe spuntare o deselezionare la casella accanto a un file prima di effettuare il check-in. Verranno impegnati solo i file controllati. La differenza con Git è che se si utilizza git add -p, è possibile scegliere di eseguire il commit di una parte di un file senza commettere un'altra parte dello stesso file .
Kyralessa,

Ho scoperto che questo link riassume la maggior parte di ciò che è stato risposto qui e aggiunge alcuni altri casi d'uso per giustificare la necessità di messa in scena.
Veverke,

2
Questa domanda è in realtà già risposto, ma qui è anche una buona spiegazione: stackoverflow.com/questions/4878358/...
guitar_freak

1
Non dimenticare git statuse possibilmente git push. Per tutto l'hype su git, (e il codice di condivisione GitHub è meraviglioso) le parti sono molto fastidiose
user949300

Risposte:


83

Dividi il lavoro in commit separati. Probabilmente hai aperto molte volte un file per scrivere una correzione a riga singola, ma allo stesso tempo hai notato che la formattazione era errata, alcuni documenti potevano essere migliorati o qualche altra correzione non correlata. Con altri RCS dovresti scriverlo o impegnarlo nella memoria, terminare la correzione per cui sei venuto, impegnarlo e poi tornare a riparare le altre cose (o creare un commit palla-di-fango con cose non correlate) . Con Git hai risolto tutto in una volta, e stage + commit la riga singola separatamente, con git add -io git-gui.

Non rompere la build. Stai lavorando a una modifica complicata. Quindi provi cose diverse, alcune delle quali funzionano meglio di altre, altre che spezzano le cose. Con Git metteresti in scena le cose quando la modifica rendeva le cose migliori e checkout(o modificane un po 'di più) quando la modifica non funzionava. Non dovrai fare affidamento sulla funzionalità di annullamento dell'editor, puoi checkoutl'intero repository anziché solo file per file e qualsiasi errore a livello di file (come la rimozione di un file che non è stato eseguito il commit o il salvataggio + chiusura dopo un modifica errata) non comporta la perdita di molto lavoro.


3
Proveniente da un DVCS (bzr) che non ha questa funzione, che assomiglia molto a quello che attualmente ottengo con una combinazione di uso liberale dei buffer "annulla" del mio editor, il comando "ripristina <file>" e commit selettivi (" commit <file> "). Sembra che questa caratteristica di Git abbia il potenziale per essere più metodica.
thomasrutter,

1
Per quanto riguarda "altri RCS", ciò non è necessariamente vero. In effetti, puoi ottenere le stesse funzionalità in Mercurial usando le patch .
Lucio Paiva,

1
@ l0b0, sul tuo secondo punto. Se ci fosse solo un unico stage commit, avresti potuto semplicemente eseguire il commit delle modifiche (che usi con git add) direttamente come commit. Se hai scoperto di aver fatto qualcosa di sbagliato, avresti semplicemente eliminato il commit e tornato al punto in cui ti trovavi prima di effettuare il commit. Con il concetto di messa in scena, non lo stai solo facendo, ma aggiungendo più complessità?
alpha_989,

Il tuo primo punto ha senso, anche se non l'ho usato finora. Teoricamente, perché non riesci a fare qualcosa come un git add -icon un unico stage? Dovresti semplicemente scegliere un mucchio di file (o linee all'interno di file) relativi a una singola funzione e fare un commit. Quindi
torneresti a

@thomasrutter, Dalla tua affermazione, sembra che tu stia suggerendo che l'area di gestione temporanea crea "punti di annullamento manuale". In VIM con persistente-annulla, puoi ottenere una cronologia illimitata in modo molto affidabile. Anche questo viene tracciato automaticamente in un git-branchmodo ( jovicailic.org/2017/04/vim-persistent-undo ). Inoltre, la cronologia degli annullamenti viene tracciata automaticamente ogni volta che si passa alla modalità normale. Quindi riduce il carico mentale di dover creare "punti di annullamento manuali". Perché utilizzare i buffer degli editor "annulla" non è metodico?
alpha_989,

65

Uno dei vantaggi per me è la possibilità di "aggiungere" file progressivamente. Prima di impegnarmi, rivedo ogni file. Dopo aver esaminato il file, lo aggiungo. Quando io git statuso git diff, git mi mostra solo i file che sono stati modificati e non ancora aggiunti. Quando ho esaminato tutti i file e li ho aggiunti, posso impegnarmi.

Quindi sì, trovo molto utile l'area di stadiazione.

E no, non lo uso mai git commit -a. Tuttavia, lo uso spesso git add -u. In questo modo posso ancora visualizzare ciò che deve essere commesso.


2
Esattamente. Il vantaggio è un controllo molto più preciso su ciò che stai commettendo.
Josh K,

cosa succede quando si mette in scena un file più volte? viene "unito" nell'area di gestione temporanea?
m4l490n,

21

Il vantaggio è abbastanza semplice: ti dà il pieno controllo su quali file vuoi impegnare quando. Per questo motivo, puoi usare git add -pper controllare quali linee vuoi commettere.


2
Mi sono sempre chiesto come farlo. Vorrei che ci fosse un file in .gitignorelinesmodo da poter apportare modifiche locali alle singole linee che potrebbero sopravvivere agli commit e rimanere intatte.
alex gray,

3
@ReinHenrichs, pensa ai file di configurazione che devono essere modificati da ogni sviluppatore.
Ian,

1
@Ian Quindi parte del file cambia di rado e viene condivisa e parte del file cambia spesso, in modo incompatibile, e non viene condivisa? Supportare questa falsa connascenza sembra decisamente un anti-funzionalità.
Rein Henrichs,

1
@ReinHenrichs, sì ed è molto comune quando il file contiene il nome del server di database e ogni sviluppatore ha il proprio database.
Ian

4
@Ian Il tuo problema è proprio lì, che hai un file che dovrebbe essere la configurazione dell'applicazione e che contiene anche una configurazione specifica per macchina / sviluppatore. Tutti i sistemi di configurazione che conosco ti consentono di dividerlo in più file. Quindi ad esempio hai il tuo app.confche contiene le cose che vuoi condividere, e poi un db.confche hai appena inserito nell'elenco .gitignore. Problema risolto. Se stai usando qualcosa di proprietario, dovresti davvero cercare di ottenere qualcosa di così semplice. Oppure passalo attraverso un preprocessore in un evento pre-build. Molte soluzioni lì.
Aidiakapi,

1

Uno dei vantaggi che mi piace è la possibilità di impegnare una parte di un cambiamento. Vale a dire, usando git add -e. Non commetto tutte le volte che dovrei a volte, e il comando git add -e mi consente di svelare le mie modifiche in una certa misura.

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.