Perché git pull esegue un'unione invece di un rebase per impostazione predefinita?

69

Considera la seguente situazione:

  • Hai un clone di un repository git
  • Hai alcuni commit locali (commit che non sono stati ancora spinti ovunque)
  • Il repository remoto ha nuovi commit che non hai ancora riconciliato

Quindi qualcosa del genere:

Seeseguigitpullconleimpostazionipredefinite,otterraiqualcosadisimileaquesto:

Questoperchégithaeseguitoun'unione.

C'èun'alternativa,però.Puoiinvecedireapulldifareunrebase:

gitpull--rebase

eotterraiquesto:

Amioparere,laversionerebasedpresentanumerosivantaggichesiconcentranoprincipalmentesulmantenimentodelcodiceedellacronologia,quindisonounpo'colpitodalfattochegitsifondadidefault.Sì,glihashdeituoicommitlocaliverrannomodificati,maquestosembraunpiccoloprezzodapagareperlacronologiapiùsemplicecheottieniincambio.

Perònonstosuggerendochequestosiainqualchemodoundifettooundifetto,comunque.Stosoloavendoproblemiapensareaimotivipercuil'unionepotrebbeesserepreferitaperildefault.Abbiamoqualcheideasulperchéèstatoscelto?Cisonodeivantaggichelorendonopiùadattocomepredefinito?

Lamotivazioneprincipaleperquestadomandaèchelamiaaziendastacercandodistabilirealcunistandarddiriferimento(sispera,piùsimiliallelineeguida)sucomeorganizziamoegestiamoinostrirepositoryperrenderepiùfacileaglisviluppatoril'accessoaunrepositorychenonhannofunzionatoconprima.Sonointeressatoacreareuncasochedovremmodisolitoribattereinquestotipodisituazione(eprobabilmenteperraccomandareaglisviluppatoridiimpostarelaloroconfigurazioneglobaleperrebasedidefault),masefossicontrarioaquesto,michiedereiperchérebasenonètl'impostazionepredefinitaseècosìeccezionale.Quindimichiedosec'èqualcosachemimanca.

Èstatosuggeritochequestadomandasiaunduplicatodi Perché molti siti Web preferiscono "git rebase" a "git merge" “?; tuttavia, quella domanda è in qualche modo il reverse di questo. Discute i meriti di rebase su merge, mentre questa domanda si interroga sui vantaggi di unire su rebase. Le risposte qui riflettono questo, concentrandosi sui problemi con l'unione e i vantaggi di rebase.

    
posta jpmc26 11.01.2016 - 07:22
fonte

4 risposte

55

È difficile sapere con certezza perché l'unione è l'impostazione predefinita senza che venga ascoltata la persona che ha preso quella decisione.

Ecco una teoria ...

Git non può presumere che sia ok per --rebase ogni tiro. Ascolta come suona. "Rebase ogni tiro." sembra sbagliato se usi richieste pull o simili. Vuoi rebase su una richiesta pull?

In un team che non utilizza solo Git per il controllo del codice sorgente centralizzato ...

  • È possibile eseguire il pull da upstream e downstream. Alcune persone fanno un sacco di tiri da downstream, da contributori, ecc.

  • È possibile lavorare sulle funzionalità in stretta collaborazione con altri sviluppatori, estrapolandole o da un ramo di argomenti condivisi e ancora occasionalmente aggiornate dall'upstream. Se si esegue sempre il rebase, si finisce per cambiare la cronologia condivisa, per non parlare di divertenti cicli di conflitto.

Git è stato progettato per un grande team altamente distribuito dove tutti non tirano e spingono verso un singolo repository centrale. Quindi l'impostazione predefinita ha un senso.

  • Gli sviluppatori che non sanno quando è corretto rebase si uniranno per impostazione predefinita.
  • Gli sviluppatori possono eseguire il rebase quando lo desiderano.
  • I committer che fanno un sacco di pull e hanno un sacco di pull ottengono il default che gli conviene.

Per la prova di intenti, ecco un link a una nota e-mail di Linus Torvalds con le sue opinioni su quando non dovrebbero rebase. Dri-devel git pull email

Se segui l'intera discussione puoi vedere che uno sviluppatore sta prelevando da un altro sviluppatore e Linus sta estraendo da entrambi. Rende la sua opinione abbastanza chiara. Poiché probabilmente ha deciso le impostazioni predefinite di Git, questo potrebbe spiegare perché.

Un sacco di persone ora usano Git in modo centralizzato, dove tutti in un piccolo team attingono solo da un repository centrale upstream e spingono verso lo stesso telecomando. Questo scenario evita alcune delle situazioni in cui un rebase non è buono, ma di solito non lo elimina.

Suggerimento: non applicare una politica di modifica del valore predefinito. Ogni volta che metti Git insieme a un grande gruppo di sviluppatori, alcuni sviluppatori non comprenderanno Git molto profondamente (me compreso). Andranno su Google, SO, riceveranno consigli sui libri di cucina e poi si chiederanno perché alcune cose non funzionano, ad es. perché git checkout --ours <path> ottiene la versione errata del file? Puoi sempre rivedere il tuo ambiente locale, creare alias, ecc. Secondo i tuoi gusti.

    
risposta data 11.01.2016 - 10:28
fonte
15

Se leggi la manpage git per rebase, dice :

Rebasing (or any other form of rewriting) a branch that others have based work on is a bad idea: anyone downstream of it is forced to manually fix their history. This section explains how to do the fix from the downstream’s point of view. The real fix, however, would be to avoid rebasing the upstream in the first place.

Penso che lo dica abbastanza bene come ragione per non usare affatto rebase, figuriamoci farlo automaticamente per ogni tiro. Alcune persone ritengono rebase essere dannoso . Forse non dovrebbe mai essere messo in discussione, come tutto ciò che sembra fare è migliorare la storia, qualcosa che non dovrebbe essere necessario in qualsiasi SCM il cui unico lavoro essenziale è quello di preservare la storia.

Quando dici 'mantenere ... la storia pulita', pensa di sbagliare. Può sembrare più bello, ma per uno strumento progettato per mantenere una cronologia delle revisioni, è molto più pulito mantenere ogni commit in modo da poter vedere cosa è successo. Sanificare la storia in seguito è come levigare la patina, facendo apparire un ricco antico come una lucida repro: -)

    
risposta data 11.01.2016 - 15:53
fonte
12

Hai ragione, assumendo che tu abbia un solo repository locale / modificato. Tuttavia, considera l'esistenza di un secondo PC locale, ad esempio.

Una volta che la tua copia locale / modificata viene spostata da qualche altra parte, la rebasing rovinerà quelle copie. Certo, potresti forzare a spingere, ma questo diventa rapidamente complicato. Cosa succede se uno o più di questi hanno un altro commit completamente nuovo?

Come puoi vedere, è molto situazionale, ma la strategia di base sembra (per me) molto più pratica nei casi non speciali / di collaborazione.

Una seconda differenza: la strategia di fusione manterrà una struttura chiara e coerente nel tempo. Dopo i rebases è molto probabile che i commit più vecchi possano seguire le modifiche più recenti, rendendo più difficile comprendere l'intera storia e il suo flusso.

    
risposta data 11.01.2016 - 08:25
fonte
6

La grande ragione è probabilmente che il comportamento predefinito dovrebbe "funzionare" solo nei repository pubblici. Ribaltare la cronologia che altre persone hanno già unito causerà loro dei problemi. So che stai parlando del tuo repository privato, ma in generale git non sa o non importa cosa sia privato o pubblico, quindi il default scelto sarà l'impostazione predefinita per entrambi.

Io uso git pull --rebase abbastanza nel mio repository privato, ma anche lì ha un potenziale svantaggio, che è che la cronologia del mio HEAD non riflette più l'albero come ho effettivamente lavorato su di esso.

Quindi, per un grande esempio, supponiamo di eseguire sempre dei test e di assicurarmi che passino prima di eseguire un commit. Questo ha meno rilevanza dopo che ho fatto un git pull --rebase , perché non è più vero che l'albero in ognuno dei miei commit ha superato i test. Finché i cambiamenti non interferiscono in alcun modo, e il codice I pull è stato testato, allora presumibilmente avrebbe superato i test, ma non lo sappiamo perché non l'ho mai provato. Se l'integrazione continua è una parte importante del tuo flusso di lavoro, allora qualsiasi tipo di rebase in un repository che è in CI è preoccupante.

Non mi dispiace, ma disturba alcune persone: preferirebbero che la loro storia in git riflettesse il codice su cui effettivamente lavoravano (o forse nel momento in cui lo spingevano, una versione semplificata della verità dopo qualche uso di "fixup").

Non so se questo problema in particolare sia la ragione per cui Linus ha scelto di fondere piuttosto che ribasare per impostazione predefinita. Potrebbero esserci altri svantaggi che non ho incontrato. Ma dal momento che non è timido di esprimere la sua opinione in codice, sono abbastanza sicuro che si tratta di un flusso di lavoro adatto per le persone che non vogliono pensarci troppo (e specialmente quelli che lavorano in un pubblico piuttosto di un repository privato). Evitare linee parallele nel grazioso grafico, a favore di una linea retta pulita che non rappresenti lo sviluppo parallelo così come è successo, probabilmente non è la sua priorità assoluta anche se è tua: -)

    
risposta data 11.01.2016 - 15:27
fonte

Leggi altre domande sui tag