2013-08-08 6 views
12

Nella documentazione git-config all'indirizzo pull.rebase:Git pull.rebase questa è un'operazione potenzialmente pericolosa

pull.rebase

Quando vera, REBASE rami in cima al ramo recuperata, invece di unire il ramo predefinito dal remoto predefinito quando viene eseguito "git pull" su . Vedere "branch..rebase" per l'impostazione su base per ramo.

NOTA: questa è un'operazione potenzialmente pericolosa; non usarlo a meno che non si sia a capire le implicazioni (vedere git-rebase (1) per i dettagli).

Qualcuno potrebbe descrivere in dettaglio cosa significa "NOTE: this is a possibly dangerous operation; do not use it unless you understand the implications (see git-rebase(1) for details)"?

+1

Qualcuno nel tuo team sta tirando le modifiche direttamente dalla tua copia del repository (al contrario di una copia centrale a cui tutti spingono)? – Gareth

+0

Gareth, stiamo utilizzando il processo in azienda quando abbiamo un solo repository e non supportiamo qualcosa come "fork" in GitHub. – erkfel

risposta

14

Diciamo che avete questi repository Git:

  • tuo repo privata, seduto sul tuo computer di lavoro;
  • il tuo deposito pubblico, you, ospitato da qualche parte;
  • un repository principale, origin, che è l'albero di sviluppo principale.

Stai lavorando su qualcosa e hai fatto due commit A e B. Li hai pubblicati al tuo repo pubblico. Nello stesso tempo, ha un altro origin commettere Z.

 /-A-B master, you/master 
o-o-o 
    \-Z origin/master 

Ora diciamo che un collega ha bisogno dei vostri due commit per iniziare una nuova funzionalità. Tira il tuo ramo dal tuo repo pubblico e fa qualche commit su quello.

  /-C-D-E colleague/master 
    /-A-B master, you/master 
o-o-o 
    \-Z origin/master 

ora si desidera aggiungere la due, completamente testato, commette in cima origin/master. Recupera da origin e crea un rebase (che equivale a git pull --rebase o git pull con l'opzione di opzione pull.rebase). Ciò crea due commit nuovi. Li spinge al tuo repo pubblico e al origin. Per complicare ulteriormente le cose, diciamo che un nuovo commit F viene inviato a origin dopo.

 /-A-B-C-D-E colleague/master 
o-o-o 
    \-Z-A'-B'-F master, you/master, origin/master 

Ora il problema è che il vostro collega ha qualche lavoro basato su due "deprecato" si impegna, e per evitare ulteriori complicazioni (conflitti quando si uniscono, rovinare la storia) deve rebase suo ramo in cima B'(diciamo che non vuole F). Devi dirglielo, altrimenti forse non si accorgerà di quello che hai fatto.

  /-C-D-E colleague/master 
o-o-o-Z-A'-B'-F master, you/master, origin/master 

Se non lo hai detto, poi sarebbe fondere la sua filiale di nuovo in origine e la storia sarebbe simile a questa:

 /-A-B-C-D-E 
o-o-o   \ 
    \-Z-A'-B'-F-M colleague/master, origin/master 

Lei ha il doppio della A e B si impegna, anche se con nomi diversi. La cronologia diventa più difficile da leggere, e tu esegui conflitti di fusione. E ricorda questo esempio è abbastanza semplice. Se ci sono decine di persone che lavorano al progetto e origin si sta muovendo velocemente, la cronologia diventerà presto un casino completo.

Se è solo un collega, probabilmente sta bene. Ma se non sai esattamente chi ti ha strappato, non puoi sapere chi devi avvisare. È particolarmente vero nello sviluppo open source.

La regola principale è: non rebase i commit che hai già pubblicato. Se A e B fossero solo nel tuo repository privato, la rebasing è soddisfacente ed è probabilmente la cosa migliore da fare, perché rende la storia più semplice e significativa. Una storia divergente è significativa solo quando il ramo ha una buona ragione per esistere (ad esempio un ramo di una caratteristica).

+0

Quindi, se fai sempre 'git pull --rebase' sei dalla parte della sicurezza? –

+1

Se c'è un solo repository remoto con cui interagisci: sì, ed è probabilmente la migliore pratica IMHO.Se hai più di un telecomando, allora no, devi stare attento a quali commit hai già spinto da qualche parte e potrebbe essere ribattezzato da 'pull --rebase'. – Pikrass

+0

Nota che probabilmente va bene se dici a tutti che un dato ramo che pubblichi potrebbe essere ribasato in qualsiasi momento. Questo è ciò che fa Julio Hamano, il manutentore di Git, con il ramo 'pu' di git.git: questo ramo non segue una progressione lineare (è "ricreato" ogni volta) e la documentazione dice chiaramente di non basare un ramo sopra esso. – Pikrass

9

Rebase è un comando utilizzato per riscrivere la cronologia dei commit e la riscrittura dei commit causa la modifica degli ID SHA. Rifondando i propri commit privati ​​che nessun altro ha basato il proprio lavoro (cioè commetti sopra) va bene.

Tuttavia, si esegue nei guai quando si REBASE condiviso storia pubblica, perché altre persone che hanno la vecchia storia che si Ribasato sono costretti a sincronizzare o ripristinare i loro commit sulla parte superiore della nuova storia (che può potenzialmente essere un difficile processo), o cercare di risolvere la vecchia storia con quella nuova, che produrrà sicuramente conflitti. Dal official Linux Kernel Git documentation for rebase:

rebasing (o qualunque altra forma di riscrittura) un ramo che altri hanno basato il lavoro su è una cattiva idea: chiunque a valle dello stesso è costretto a correggere manualmente la loro storia.

Pertanto, non è necessario rebase commit a meno che non si sia sicuri che nessun altro condivide quei commit che si stanno ridefinendo.

Detto questo, dovresti davvero imparare a rebase però, sia interattivamente che in modo non interattivo, perché è lo strumento più potente ed efficace nell'arsenale di Git, e se non sai come usarlo, allora sei non usare Git in modo efficace.

È possibile ottenere ulteriori informazioni sulla ridefinizione dalla sezione Rewriting History dello free online Pro Git book e, naturalmente, lo official Linux Kernel Git documentation for rebase è eccellente.

+1

Grazie a Cupcake, tutto è perfettamente descritto nella documentazione, ho solo cercato di capire se ci sono trucchi nascosti con rebasing che non sono scritti nella documentazione. Il problema che sto cercando di risolvere è che con 'pull' regolare ci sono un sacco di commit non necessari nel repository, l'opzione' --rebase' aiuta, ma gli sviluppatori hanno sempre dimenticato di usarlo, quindi ho guardato ad alcuni modo automatico, ma mi sto rendendo conto che è pericoloso. – erkfel

+0

A seconda del flusso di lavoro, è anche probabile che un 'rebase' non sia mai pericoloso. Se i tuoi sviluppatori spingono e prelevano sempre da uno stesso repository "centrale" e non pubblicano i loro commit altrove o recuperano l'uno dall'altro, puoi impostare "pull.rebase": i commit rebased saranno sempre quelli che non sono " t pubblicato ancora. – Pikrass

0

Vale la pena di ricordare che un "cambiamento male" da un "evil merge" può essere perso silenziosamente mentre rebasing un "merge male" che contiene un "cambiamento del male", che non sia in conflitto con altri commit.