Qual è il modo migliore (e più sicuro) per unire un ramo Git in master?


2104

Viene mastercreato un nuovo ramo da , lo chiamiamo test.

Esistono diversi sviluppatori che si impegnano mastero creano altri rami e successivamente si uniscono master.

Supponiamo che il lavoro testrichieda alcuni giorni e si desidera essere costantemente testaggiornati con gli commit interni master.

Vorrei fare git pull origin masterda test.

Domanda 1: è questo l'approccio giusto? Altri sviluppatori avrebbero potuto facilmente lavorare sugli stessi file in cui ho lavorato tra l'altro.


Il mio lavoro testè finito e sono pronto a ricollegarlo master. Ecco i due modi in cui posso pensare:

UN:

git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test 

B:

git checkout test
git pull origin master
git checkout master
git merge test

Non sto usando --rebaseperché dalla mia comprensione, rebase otterrà i cambiamenti da mastere impilerà il mio su quello, quindi potrebbe sovrascrivere i cambiamenti fatti da altre persone.

Domanda 2: quale di questi due metodi è giusto? Qual è la differenza lì?

L'obiettivo di tutto ciò è mantenere il mio testramo aggiornato con le cose che accadono mastere in seguito potrei fonderle nuovamente nella mastersperanza di mantenere la linea temporale il più lineare possibile.


18
no .. rebase non sovrascrive mai, sta solo cercando di ottenere una storia più pulita. riattaccando (o falsificando) la storia fino alla fine del maestro
Junchen Liu,

7
rebase non sovrascrive i tuoi commit. Annulla i commit, applica i commit nel ramo master al ramo di test, quindi applica nuovamente i commit al test.
zundi,

Risposte:


2994

Come lo farei

git checkout master
git pull origin master
git merge test
git push origin master

Se ho una filiale locale da una remota, non mi sento a mio agio nel fondere altre filiali diverse da questa con il telecomando. Inoltre non spingerei i miei cambiamenti, fino a quando non sarò contento di ciò che voglio spingere e non spingerei affatto le cose, che sono solo per me e il mio repository locale. Nella tua descrizione sembra che testsia solo per te? Quindi nessun motivo per pubblicarlo.

git cerca sempre di rispettare i tuoi e altri cambiamenti, e così farà --rebase. Non credo di poterlo spiegare in modo appropriato, quindi dai un'occhiata al libro Git - Rebasing o git-ready: introduzione al rebasing per una breve descrizione. È una caratteristica piuttosto interessante


2
git merge testmi dà fatal: 'test' does not point to a commit. Devo cercare git logil punto di commit sul ramo di prova, tornare al ramo principale e poi fare git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234.
Duncanmoo,

17
@Duncanmoo Bene, ovviamente testdeve esistere il ramo . Certo, puoi usare invece l'hash di commit, ma di solito è più facile usare il nome del ramo. Internamente recupera solo l'hash del HEADramo.
KingCrunch

44
@shanyangqu Per ottenere le ultime modifiche dal telecomando. Se lavori da solo e con un solo sistema, non c'è nessun problema. Ma quando ci sono cambiamenti spinti da un sistema diverso (probabilmente da un altro sviluppatore) vedrai un conflitto non appena provi a respingere la tua unione (il quarto passo). L'unica soluzione ora è quella di unire il tuo master locale al master dei telecomandi, che finisce in un brutto commit di unione "master unito in origine / master". Quindi è sempre una buona idea fare un tiro prima della fusione
KingCrunch,

7
"Nella tua descrizione sembra che quel test sia solo per te? Quindi nessun motivo per pubblicarlo." Potresti voler spingere la tua filiale locale su un server se, ad esempio, quel server fornisce un backup contro il guasto dell'unità locale o se non hai altri mezzi per eseguire un backup.
Eric,

5
"... Inoltre non spingerei le mie modifiche, fino a quando non sarò contento di ciò che voglio spingere ..." perché non spingere per il bene di avere il backup del codice, nel caso in cui le macchine locali muoiano e giorni di sforzi sono andati?
Rich Stone

400

Questa è una domanda molto pratica, ma tutte le risposte sopra non sono pratiche.

Piace

git checkout master
git pull origin master
git merge test
git push origin master

Questo approccio ha due problemi :

  1. Non è sicuro, perché non sappiamo se ci sono conflitti tra il ramo test e il ramo master.

  2. "Comprime" tutti i commit di test in un commit di merge sul master; vale a dire sul ramo principale, non possiamo vedere tutti i registri delle modifiche del ramo di prova.

Quindi, quando sospettiamo che ci siano alcuni conflitti, possiamo avere le seguenti operazioni git:

git checkout test
git pull 
git checkout master
git pull
git merge --no-ff --no-commit test

Prova mergeprima commit, evita un commit rapido da --no-ff,

Se si verificano conflitti, possiamo eseguire git statusper controllare i dettagli sui conflitti e provare a risolverli

git status

Una volta risolti i conflitti, o in assenza di conflitti, noi commite pushloro

git commit -m 'merge test branch'
git push

Ma in questo modo si perderà la cronologia delle modifiche registrata nel ramo di prova e renderebbe difficile il ramo principale per gli altri sviluppatori per comprendere la storia del progetto.

Quindi il metodo migliore è che dobbiamo usare rebaseinvece di merge(supponiamo, quando in questo momento, abbiamo risolto i conflitti del ramo).

Di seguito è riportato un semplice esempio, per operazioni avanzate, fare riferimento a http://git-scm.com/book/en/v2/Git-Branching-Rebasing

git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test

Sì, quando hai terminato la tomaia, tutti i commit del ramo Test verranno spostati sul capo del ramo Master. Il principale vantaggio del rebasing è che ottieni una cronologia del progetto lineare e molto più pulita.

L'unica cosa che devi evitare è: non utilizzare mai rebasesu una filiale pubblica, come la diramazione principale.

Non eseguire mai operazioni come le seguenti:

git checkout master
git rebase -i test

Dettagli per https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing

appendice:


4
Sono d'accordo nel ripetere il ramo di prova per la successiva fusione in master è la strada da percorrere. Anche le altre risposte sono corrette, ciò manterrà la cronologia dei cambiamenti del test di ramo nella testa del master, poiché la menzione automatica "ottieni un progetto più lineare e molto più pulito", che è lo scopo del sistema di controllo della versione.
le0diaz,

16
L'affermazione "non è un modo di sicurezza, perché non sappiamo che ci sono conflitti tra il ramo di test e il ramo principale" non è vera: si può sempre interrompere l'unione. E anche se non ci sono conflitti, puoi sempre annullare l'ultimo commit locale purché non venga spinto. Senza una corretta comprensione di git alcune cose possono sembrare un po 'spaventose o poco chiare, ma "insicuro" non è corretto in alcun modo. Si prega di fare attenzione a non confondere gli altri con informazioni errate.
Paul van Leeuwen,

4
concordare con @PaulvanLeeuwen, quando si unisce il ramo di prova in master, si riceverà una notifica relativa ai conflitti ed è qui che si interverranno e si uniranno le modifiche. Una volta che hai finito, commetterai l'unione e respingerai. Se ti penti o non riesci a fonderlo correttamente, puoi sempre scartare il tuo lavoro ed estrarre di nuovo dal master. Quindi non è assolutamente pericoloso ..
Juan

3
perché rebase -i?
MushyPeas,

8
Rebasing è intrinsecamente più pericoloso della fusione. Proporre il rebasing come opzione più sicura per la fusione è sbagliato. Rebasing è una strategia valida, ma include più avvertimenti di cui l'utente dovrebbe fare attenzione.
Ikke,

90

Né un rebase né una fusione dovrebbero sovrascrivere le modifiche di nessuno (a meno che non si scelga di farlo quando si risolve un conflitto).

L'approccio abituale durante lo sviluppo è

git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier

Quando sei pronto per ricollegarti al maestro,

git checkout master
git log ..test # if you're curious
git merge test
git push

Se sei preoccupato di rompere qualcosa nell'unione, git merge --abortè lì per te.

Usare push e quindi pull come mezzo di fusione è sciocco. Inoltre non sono sicuro del motivo per cui stai spingendo il test all'origine.


1
Questo processo aumenterà il numero di commit, ogni volta che si passa da una filiale all'altra, è necessario eseguire il commit della filiale.
iBug

2
Che cosa? Stai dicendo che aumenterà il numero di commit ogni volta che cambi filiali? O stai dicendo che ogni volta che cambi ramo, devi "impegnare il tuo ramo"? Il primo è falso e non sono sicuro di cosa significhi il secondo.
raylu,

prima del checkout, devi impegnare la filiale. questo è quello che sto dicendo
iBug

11
No: questo è (una delle cose) git stashè per.
msanford,

1
Oppure potresti apportare il tuo ultimo commit (nella filiale locale) e renderlo perfetto prima di spingere.
Whihathac,

42

Innanzitutto renderei il ramo da unire il più pulito possibile. Esegui i test, assicurati che lo stato sia come desideri. Pulisci i nuovi commit con Git Squash .

Oltre alla risposta di KingCrunches , suggerisco di usare

git checkout master
git pull origin master
git merge --squash test
git commit
git push origin master

Potresti aver effettuato molti commit nell'altro ramo, che dovrebbe essere solo un commit nel ramo principale. Per mantenere la cronologia dei commit il più pulita possibile, potresti voler comprimere tutti i tuoi commit dal ramo test in un commit nel ramo master (vedi anche: Git: schiacciare o non schiacciare? ). Quindi puoi anche riscrivere il messaggio di commit in qualcosa di molto espressivo. Qualcosa che è facile da leggere e capire, senza scavare nel codice.

modifica: potrebbe interessarti

Quindi su GitHub, finisco per fare quanto segue per un ramo di funzionalità mybranch:

Ricevi le ultime dall'origine

$ git checkout master
$ git pull origin master

Trova l'hash base unione:

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

Ora assicurati che solo il primo sia pick, il resto è s:

pick 00f1e76 Add first draft of the Pflichtenheft
s d1c84b6 Update to two class problem
s 7486cd8 Explain steps better

Quindi scegli un ottimo messaggio di commit e passa a GitHub. Invia quindi la richiesta pull.

Dopo l'unione della richiesta pull, puoi eliminarla localmente:

$ git branch -d mybranch

e su GitHub

$ git push origin :mybranch

" che dovrebbe essere un solo commit nel ramo master ", non necessariamente; potresti voler conservare la storia
Cocowalla,

Sicuro. Ma poi semplicemente non schiacciare i commit
Martin Thoma,

Penso che il primo genitore sembra essere la soluzione migliore. davidchudzicki.com/posts/first-parent
bkribbs

7

Vecchio thread, ma non ho trovato il mio modo di farlo. Potrebbe essere utile per qualcuno che lavora con rebase e vuole unire tutti i commit da un ramo (feature) sopra al master. Se c'è un conflitto in arrivo, puoi risolverli per ogni commit. Mantenete il pieno controllo durante il processo e potete interrompere in qualsiasi momento.

Ricevi Master e Branch aggiornati:

git checkout master
git pull --rebase origin master
git checkout <branch_name>
git pull --rebase origin <branch_name>

Unisci Branch in cima al Master:

git checkout <branch_name>
git rebase master

Opzionale: Se si verificano conflitti durante il Rebase:

Innanzitutto, risolvi il conflitto nel file. Poi:

git add .
git rebase --continue

Spingi il tuo ramo rinnovato:

git push origin <branch_name>

Ora hai due opzioni:

  • A) Crea un PR (ad es. Su GitHub) e uniscilo lì tramite l'interfaccia utente
  • B) Torna alla riga di comando e unisci il ramo al master
git checkout master
git merge --no-ff <branch_name>
git push origin master

Fatto.


6

Questo è il flusso di lavoro che utilizzo nel mio lavoro con il team. Lo scenario è come hai descritto. In primo luogo, quando ho finito di lavorare, testmi cambio con master per inserire tutto ciò che è stato aggiunto a master durante il periodo in cui ho lavorato sul testramo.

git pull -r upstream master

Ciò attirerà le modifiche al master poiché hai biforcuto il testramo e le applicherà, quindi applicherà le modifiche apportate per testare "sopra" lo stato corrente del master. Potrebbero esserci dei conflitti qui, se le altre persone hanno apportato modifiche agli stessi file che hai modificato nel test. Se ci sono, dovrai ripararli manualmente e impegnarti. Una volta fatto, sarai bravo a passare al ramo principale e unirti testsenza problemi.


3
git checkout master
git pull origin master
# Merge branch test into master
git merge test

Dopo l'unione, se il file viene modificato, quando lo unisci verrà visualizzato l'errore "Risolvi conflitto"

Quindi, prima devi risolvere tutti i tuoi conflitti, quindi devi impegnare nuovamente tutte le modifiche e poi spingere

git push origin master

È meglio fare chi ha apportato modifiche al ramo di prova, perché sapeva quali modifiche ha apportato.


3

Vorrei usare il metodo rebase. Soprattutto perché riflette perfettamente il tuo caso semanticamente, vale a dire. quello che vuoi fare è aggiornare lo stato del tuo ramo attuale e "fingere" come se fosse basato sull'ultimo.

Quindi, senza nemmeno fare il check-out master, vorrei:

git fetch origin
git rebase -i origin/master
# ...solve possible conflicts here

Certo, solo il recupero dall'origine non aggiorna lo stato locale del tuo master(in quanto non esegue un'unione), ma è perfettamente ok per il nostro scopo: vogliamo evitare di cambiare, per risparmiare tempo.


2

La risposta di @ KingCrunch dovrebbe funzionare in molti casi. Un problema che può sorgere è che potresti trovarti su un altro computer che deve estrarre l'ultimo test. Quindi, consiglio di tirare prima il test. La revisione è simile alla seguente:

git checkout test
git pull
git checkout master
git pull origin master
git merge test
git push origin master

0

Devi estrarre il ramo per estrarre, poiché estrarre significa fondersi con il master e devi fondere un albero di lavoro.

git checkout master
git pull

Non è necessario verificare prima; rebase fa la cosa giusta con due argomenti

git rebase master test  

git checkout master
git merge test

git push di default spinge tutti i rami che esistono qui e sul telecomando

git push
git checkout test

0

Come dice il titolo "Il modo migliore", penso che sia una buona idea considerare la strategia di unione della pazienza .

Da: https://git-scm.com/docs/merge-strategies

Con questa opzione, "unione-ricorsiva" impiega un po 'di tempo extra per evitare discrepanze che a volte si verificano a causa di linee di corrispondenza non importanti (ad es. Parentesi graffe da funzioni distinte). Usalo quando i rami da unire sono divergenti selvaggiamente. Vedi anche git-diff [1] --patience.

Uso:

git fetch
git merge -s recursive -X patience origin/master

Git Alias

Uso sempre un alias per questo, ad esempio esegui una volta:

 git config --global alias.pmerge 'merge -s recursive -X patience'

Ora potresti fare:

git fetch
git pmerge origin/master

0

Questo è di GitLab: basta seguire le istruzioni:

inserisci qui la descrizione dell'immagine


0

Risponderò come da sviluppo e funzionalità rami,

se sei nel ramo delle funzionalità e hai bisogno di aggiornarlo con i comandi use use below: git checkout Develop git pull git checkout

Ora la tua funzione è stata aggiornata con lo sviluppo puoi spingere le tue modifiche.

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.