Rebasing e cosa si intende per rebasing pushed commit


109

Si dice spesso che non dovresti rebase i commit che hai già spinto. Che cosa potrebbe esserci di significato?

Risposte:


80

Il libro ProGit ha una buona spiegazione .

La risposta specifica alla tua domanda può essere trovata nella sezione intitolata " The Perils of Rebasing ". Una citazione da quella sezione:

Quando ribasate le cose, abbandonate i commit esistenti e ne create di nuovi simili ma diversi. Se spingi i commit da qualche parte e altri li tirano giù e ti basano sul lavoro, e poi li riscrivi con git rebase e li sposti di nuovo, i tuoi collaboratori dovranno unire nuovamente il loro lavoro e le cose si complicheranno quando proverai a ritira il loro lavoro nel tuo.

Aggiornamento: in
base al tuo commento qui sotto, sembra che tu abbia difficoltà con il tuo flusso di lavoro Git. Ecco alcuni riferimenti che possono aiutare:


Grazie per la spiegazione. Quindi, solo per rendere più chiara la mia comprensione, dopo aver spinto alcune modifiche, non dovrei usare git rebase(--interactive?) Per riscrivere quella storia, questa è la ricetta sicura del fallimento. D'altra parte, se ho ribasato alcune modifiche all'argomento branch (dal ramo X) e spingerlo, è perfettamente normale rebase di nuovo dopo che un altro sviluppatore cambia topic branch. In sostanza, lo uso mergeda un po 'di tempo, ma siamo nella stessa barca di darwinweb.net/articles/86 e la cronologia è quasi inutilizzabile.
Hemant Kumar

@Hemant: ribasare i commit dopo aver eseguito il push in un repo pubblico è generalmente una cattiva idea. Detto questo, il consiglio dell'articolo di darwinweb che hai citato sembra ragionevole se il tuo flusso di lavoro è simile al loro. Vedere la mia risposta aggiornata per un elenco di altri riferimenti che potrebbero aiutare.
Tim Henigan

Aggiorna un link alla pagina "ProGit" su "Private Managed Team" su git-scm.com/book/en/…
Eimantas

Quindi tecnicamente, i commit git rimangono gli stessi ma "abbandonare i commit esistenti e crearne di nuovi che sono simili ma diversi" sono solo lo stesso commit con un id sha1 diverso? beh questo sarebbe l'unico modo ovvio in cui riesco a pensare al motivo per cui i collaboratori dovranno unire nuovamente il proprio lavoro!
Ciasto piekarz

@Ciastopiekarz, questo è perché stai riscrivendo la cronologia nel repository a monte e i repository locali di altri sviluppatori potrebbero avere riferimenti a questo. Ora i loro puntatori sono obsoleti: il client git non ha altra alternativa che usare puntatori più vecchi e fare affidamento sull'umano per sistemare il resto. Questa è una ricongiunzione e può essere MOLTO complicata con molte modifiche confuse che devono essere risolte manualmente! Quindi la raccomandazione di non ribasare mai qualcosa che è già stato inviato a un repo a monte. Questo è un buon consiglio e non dovrebbe essere ignorato a meno che tu non sia un esperto con una profonda conoscenza.
Forbin

240

Per capirlo, dobbiamo capire un po 'come funziona git. Un repository git è una struttura ad albero, in cui i nodi dell'albero sono commit. Ecco un esempio di un repository molto semplice: Quando forzi

ha quattro commit sul ramo master e ogni commit ha un ID (in questo caso, a, b, c e d). Noterai che d è attualmente l'ultimo commit (o HEAD) del ramo master. inserisci qui la descrizione dell'immagine

Qui abbiamo due rami: master e my-branch. Puoi vedere che master e my-branch contengono entrambi commit a e b, ma poi iniziano a divergere: master contiene c e d, mentre my-branch contiene e ed f. b si dice che sia la "base di unione" del mio ramo rispetto al master - o più comunemente, solo la "base". Ha senso: puoi vedere che my-branch era basato su una versione precedente di master.

Quindi diciamo che il mio ramo è diventato obsoleto e vuoi aggiornarlo con l'ultima versione di master. Per dirla in un altro modo, my-branch deve contenere c e d. Potresti fare un'unione, ma ciò fa sì che il ramo contenga strani commit di unione che rendono molto più difficile la revisione della richiesta pull. Invece, puoi fare un rebase.

inserisci qui la descrizione dell'immagine

Quando rebase, git trova la base del tuo ramo (in questo caso, b), trova tutti i commit tra quella base e HEAD (in questo caso, e e f), e riproduce quei commit sulla HEAD del ramo stai ribasando su (in questo caso, master). Git in realtà crea nuovi commit che rappresentano come appaiono le tue modifiche sopra il master: nel diagramma, questi commit sono chiamati e ′ e f ′. Git non cancella i tuoi commit precedenti: e e f non vengono toccati, e se qualcosa va storto con il rebase, puoi tornare a come erano le cose.

Quando molte persone diverse lavorano a un progetto in modo simulato, le richieste pull possono diventare obsolete rapidamente. Una richiesta pull "obsoleta" è una richiesta che non è più aggiornata con la linea principale di sviluppo e deve essere aggiornata prima di poter essere unita al progetto. Il motivo più comune per cui le richieste pull diventano obsolete è a causa di conflitti: se due richieste pull modificano entrambe linee simili nello stesso file e una richiesta pull viene unita, la richiesta pull non unita ora avrà un conflitto. A volte, una richiesta pull può diventare obsoleta senza conflitti: forse le modifiche in un file diverso nella codebase richiedono modifiche corrispondenti nella richiesta pull per conformarsi alla nuova architettura, o forse il ramo è stato creato quando qualcuno ha accidentalmente unito gli unit test non riusciti al ramo principale. Indipendentemente dal motivo,


68

Il rebasing riscrive la storia. Se nessuno conosce quella storia, allora va benissimo. Se, tuttavia, quella storia è pubblicamente nota, riscrivere la storia in Git funziona esattamente come nel mondo reale: hai bisogno di una cospirazione.

Le cospirazioni sono davvero difficili da tenere insieme, quindi è meglio evitare di ribasare le filiali pubbliche in primo luogo.

Nota che ci sono esempi di cospirazioni di successo: il puramo del repository git di Junio ​​C. Hamano (il repository ufficiale di Git SCM) viene ribasato frequentemente. Il modo in cui funziona è che praticamente tutti quelli che usano pusono anche iscritti alla mailinglist degli sviluppatori Git, e il fatto che il puramo sia ribasato è ampiamente pubblicizzato sulla mailinglist e sul sito web di Git.


4
+1. Penso che il puramo di git.git sia un esempio estremamente utile di come utilizzare rebase in un flusso di lavoro (pubblico). Per coloro che non lo conoscono, l'idea generale è di riassegnare i rami dell'argomento che non hanno alcun commit in next(il ramo instabile appena prima di unirsi al master), quindi ricostruire il puramo ripristinando nexte unendo tutti i rami dell'argomento. (Fonte: Documentation / howto / maintain-git.txt git.kernel.org/?p=git/git.git;a=blob;f=Documentation/howto/… )
Cascabel

25
+1 per "riscrivere la storia in Git funziona esattamente come nel mondo reale: hai bisogno di una cospirazione"
Sleeper Smith

"Non è necessario un annuncio pubblico poiché pu è un ramo usa e getta, come descritto sopra." git-scm.com/docs/gitworkflows Facciamo qualcosa di simile al lavoro, "TEMP-something-latest" è un ramo usa e getta che è una combinazione delle ultime modifiche, potrebbe essere un'unione di più rami di funzionalità, potrebbe essere eliminato e ricreato in qualsiasi momento e non dovrebbe essere sviluppato.
pilkch

6

Un rebase altera la cronologia del tuo repository. Se invii i commit al mondo, ad esempio li rendi disponibili ad altri, e poi cambi la tua visione della cronologia dei commit, diventa difficile lavorare con chiunque abbia la tua vecchia storia.

Rebase considerato dannoso è una buona panoramica, credo.

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.