Care este cel mai bun (și cel mai sigur) mod de a îmbina o ramură Git în master?

Este creată o nouă ramură din master, o numim test.

Există mai mulți dezvoltatori care fie se angajează la master, fie creează alte ramuri și ulterior fuzionează în master.

Să presupunem că lucrul pe test durează câteva zile și doriți să fiți permanent actualizat pe test cu comitări în interiorul master.

Aș face git pull origin master din test.

Întrebarea 1: Este aceasta abordarea corectă? Alți dezvoltatori ar fi putut lucra cu ușurință la aceleași fișiere ca și eu.


Munca mea pe test s-a terminat și sunt gata să o îmbin în master. Iată cele două moduri la care mă pot gândi:

A:

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

Nu folosesc --rebase pentru că, din înțelegerea mea, rebase va primi modificările de la master și le va stivui pe ale mele pe deasupra, astfel încât ar putea suprascrie modificările făcute de alți oameni.

Întrebarea 2: Care dintre aceste două metode este corectă? Care este diferența acolo?

Scopul în toate acestea este să-mi mențin ramura test actualizată cu lucrurile care se întâmplă în master și mai târziu le-aș putea îmbina înapoi în master sperând să păstrez cronologia cât mai liniară posibil.


person moe    schedule 09.04.2011    source sursă
comment
nu.. rebase nu suprascrie niciodată, doar încearcă să obțină un istoric mai curat. prin reatașare (sau falsificare) istoricul până la punctul târziu al masterului   -  person Junchen Liu    schedule 23.12.2015
comment
rebase nu suprascrie comiterile tale. Îți anulează comiterile, aplică comiterile din ramura principală la ramura ta de testare, apoi le aplică înapoi la testare.   -  person zundi    schedule 20.06.2016
comment
Ce se întâmplă dacă nu avem acces de scriere la master? Vreo modalitate de a remedia conflictele în mod preventiv pe ramura caracteristică? Probabil că nu cred, din moment ce istoriile probabil au divergent   -  person information_interchange    schedule 22.07.2020


Răspunsuri (14)


Cum aș face asta

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

Dacă am o sucursală locală de la una la distanță, nu mă simt confortabil să comas alte ramuri decât aceasta cu telecomandă. De asemenea, nu mi-aș împinge modificările, până când nu sunt mulțumit de ceea ce vreau să împing și, de asemenea, nu aș împinge deloc lucrurile, care sunt doar pentru mine și pentru depozitul meu local. În descrierea ta se pare că test este doar pentru tine? Deci nu există niciun motiv să-l public.

git încearcă întotdeauna să respecte schimbările tale și ale altora, la fel și --rebase. Nu cred că pot explica în mod corespunzător, așa că aruncați o privire la cartea Git - Rebazare sau git-ready: Introducere în rebazare pentru o mică descriere. Este o caracteristică destul de cool

person KingCrunch    schedule 09.04.2011
comment
git merge test îmi dă fatal: 'test' does not point to a commit. Trebuie să caut în git log punctul de comitere pe ramura de testare, să trec înapoi la ramura principală, apoi să fac git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234. - person Duncanmoo; 02.12.2014
comment
@Duncanmoo Ei bine, bineînțeles că ramura test trebuie să existe. Sigur, puteți folosi commit hash-ul în schimb, dar de obicei este mai ușor să utilizați numele de ramură. Pe plan intern, pur și simplu preia hash-ul HEAD al ramului. - person KingCrunch; 04.12.2014
comment
@shanyangqu Pentru a obține cele mai recente modificări de la telecomandă. Dacă lucrezi singur și cu un singur sistem, nu există nicio problemă. Dar când există modificări impuse de la un alt sistem (probabil de la un alt dezvoltator), veți vedea un conflict de îndată ce încercați să vă împingeți îmbinarea înapoi (al 4-lea pas). Singura soluție acum este să îmbinați masterul local în masterul telecomenzilor, care se termină într-un master îmbinat destul de urât în ​​comiterea de îmbinare origin/master. Prin urmare, este întotdeauna o idee bună să faceți o tragere înainte de îmbinare - person KingCrunch; 25.12.2015
comment
Ați putea dori să faceți un test push dacă se va face backup numai atunci când este pe serverul dvs. central git. Acest lucru este bine mai ales dacă lucrați la propria furcă. - person Jordan Morris; 17.02.2016
comment
aceasta arată comiterile la fb (ramură de testare) ca și cum ar fi fost comise direct în master, spre deosebire de afișarea commit-urilor pe fb-ul lor original și doar îmbinarea în master (așa cum se vede cu gitk sau pe rețeaua gitlab) - person Joey Baruch; 11.05.2016
comment
Nu este mai sigur să îmbinați origin/master în test înainte de a îmbina testul în master? Nu ar face testul de mai sus depășit? - person ziggy; 17.09.2016
comment
@ziggy Ei bine... Depinde. Despre fluxul de lucru. De exemplu, mulți comit doar caracteristici și remedieri de erori în develop și numai remedieri rapide (și poate remedieri importante de erori) în master. Apoi redirecționează remedierile rapide de la develop la master (asta este ceea ce ați spus din punct de vedere tehnic). Cu toate acestea, dacă nu există o remediere rapidă (care este întotdeauna bună :)), atunci develop este întotdeauna în fața lui master. Deci da, ai dreptate, dar, în funcție de fluxul de lucru, poate pur și simplu nu este necesar. (Am folosit develop aici, pentru că este mai comun decât test). - person KingCrunch; 18.09.2016
comment
Arcul și săgeata de @sterling Archer nu se schimbă, dar scopul și strategia se pot schimba :-) - person Prasad; 13.11.2016
comment
În descrierea ta se pare, acel test este doar pentru tine? Deci nu există niciun motiv să-l public. S-ar putea să doriți să vă împingeți sucursala locală la un server dacă, de exemplu, acel server oferă o copie de rezervă împotriva defecțiunii unității dvs. locale sau dacă nu aveți alte mijloace pentru a face o copie de rezervă. - person Eric; 13.02.2017
comment
-1 Nu explică în ce depozit trebuie să executați aceste comenzi. Scor surprinzător de mare, având în vedere cât de inutil este. - person Felo Vilches; 03.10.2017
comment
@FeloVilches: Dacă înțelegeți comenzile, atunci știți pe ce ramură executați aceste comenzi. - person Nawaz; 03.10.2017
comment
@Nawaz punct valid, dar titlul spune safest way, așa că nu sunt sigur cât de sigur este să executați aceste comenzi într-o ramură aleatorie. - person Felo Vilches; 03.10.2017
comment
@FeloVilches: Nu este o ramură aleatorie! În siguranță sau nu, aceasta este o întrebare cu totul diferită. Dar nu asta a fost preocuparea ta inițială! - person Nawaz; 03.10.2017
comment
@FeloVilches Răspunsul începe cu git checkout master. Presupunând că citiți rezultatul gits, probabil că sunteți pe master după aceea. Puteți chiar să executați în siguranță git checkout master pe o ramură aleatorie :) - person KingCrunch; 13.11.2017
comment
...De asemenea, nu mi-aș împinge modificările, până când nu sunt mulțumit de ceea ce vreau să fac... de ce să nu acționez de dragul de a avea codul de rezervă, în cazul în care mașinile dvs. locale moare și zilele de eforturi au trecut? - person Rich Steinmetz; 15.08.2018
comment
Acest răspuns mi se pare greșit. OP întreabă cum să păstrați ramura de testare actualizată cu masterul - iar acest răspuns arată doar cum să îmbinați testul în master. - person asimovwasright; 16.05.2019
comment
@KingCrunch Ar trebui să șterg ramura după fuzionare? - person Oliver D; 12.03.2020
comment
@OliverD Sigur, de ce nu? Dacă o ramură este fuzionată, înseamnă că commit-urile sunt acum prezente în mai mult de o ramură. Ștergerea ramurii sursă nu va renunța la modificări. Pe de altă parte, recrearea ramurii este la doar o singură linie distanță :) git checkout -b foo master - person KingCrunch; 14.03.2020
comment
Dacă git merge testfatal: refusing to merge unrelated histories atunci git merge test --allow-unrelated-histories de lucru. - person Upulie Han; 23.10.2020
comment
Încă un lucru .. new git folosesc main și nu master - person LonelySoul; 07.02.2021

Aceasta este o întrebare foarte practică, dar toate răspunsurile de mai sus nu sunt practice.

Ca

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

Această abordare are două probleme:

  1. Este nesigur, deoarece nu știm dacă există conflicte între ramura de testare și ramura principală.

  2. Ar „strânge” toate comiterile de testare într-un singur comit de îmbinare pe master; adică pe ramura principală, nu putem vedea toate jurnalele de modificări ale ramurii de testare.

Deci, atunci când bănuim că ar exista unele conflicte, putem avea următoarele operații git:

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

Testați merge înainte de commit, evitați o comitere rapidă înainte de --no-ff,

Dacă se întâlnește un conflict, putem rula git status pentru a verifica detaliile despre conflicte și a încerca să le rezolvăm

git status

Odată ce rezolvăm conflictele, sau dacă nu există conflict, le commit și push

git commit -m 'merge test branch'
git push

Dar în acest fel se va pierde istoricul modificărilor înregistrate în ramura de testare și ar face ca ramura principală să fie dificilă pentru alți dezvoltatori să înțeleagă istoria proiectului.

Deci, cea mai bună metodă este să folosim rebase în loc de merge (să presupunem că, în acest timp, am rezolvat conflictele de ramuri).

Mai jos este un exemplu simplu, pentru operațiuni avansate, vă rugăm să consultați 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

Da, când ai terminat upper, toate commit-urile ramului Test vor fi mutate în șeful ramului Master. Beneficiul major al rebazării este că obțineți un istoric al proiectului liniar și mult mai curat.

Singurul lucru pe care trebuie să-l evitați este: nu utilizați niciodată rebase pe ramura publică, cum ar fi ramura principală.

Nu efectuați niciodată operațiuni precum următoarele:

git checkout master
git rebase -i test

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

apendice:

person John Yin    schedule 14.03.2015
comment
dacă nu sunteți sigur de operațiunea de rebase, vă rugăm să consultați: git-scm .com/book/en/v2/Git-Branching-Rebasing - person John Yin; 05.03.2016
comment
Sunt de acord că rebazarea ramurii de testare pentru fuzionarea ulterioară în master este calea de urmat. Chiar și celelalte răspunsuri sunt corecte, acest lucru va păstra istoricul modificărilor de testare a ramurilor în șeful masterului, deoarece autorul menționează că obțineți un proiect de linie și mult mai curat, care este scopul sistemului de control al versiunilor. - person le0diaz; 05.05.2016
comment
Afirmația că nu este o singură cale de siguranță, pentru că nu știm dacă există conflicte între ramura de testare și ramura principală nu este adevărată: oricând se poate anula îmbinarea. Și chiar dacă nu există conflicte, puteți anula întotdeauna ultimul commit local, atâta timp cât nu este împins. Fără înțelegerea corectă a git, unele lucruri pot părea puțin înfricoșătoare sau neclare, dar nesigur este pur și simplu incorect în orice fel. Vă rugăm să aveți grijă să nu confundați pe alții cu informații incorecte. - person Paul van Leeuwen; 18.08.2016
comment
de acord cu @PaulvanLeeuwen, când git merge ramura de testare în master, veți fi notificat despre conflicte și acolo veți interveni și vei îmbina modificările. După ce ați terminat, veți comite fuzionarea și veți respinge înapoi. Dacă regretați sau nu puteți să-l îmbinați corect, puteți oricând să renunțați la munca dvs. și să trageți din nou de la master. Deci cu siguranță nu este nesigur.. - person Juan; 09.10.2016
comment
de ce rebase -i? - person MushyPeas; 16.06.2017
comment
Rebazarea este în mod inerent mai nesigură decât fuzionarea. Este greșit să propui rebazarea ca o opțiune mai sigură pentru fuziune. Rebazarea este o strategie validă, dar vine cu mai multe avertismente de care utilizatorul ar trebui să se ferească. - person Ikke; 31.03.2018
comment
Pentru cei care au avut conflicte la rebazare, puteți rezolva conflictele și puteți rula git rebase --continue. Am reușit să îmbin cu succes ramura mea de dezvoltare. Deci, acum este sigur să șterg ramura dev dacă nu o mai folosesc? - person Lasithds; 10.05.2019

Nici o rebazare, nici o îmbinare nu ar trebui să suprascrie modificările nimănui (cu excepția cazului în care alegeți să faceți acest lucru atunci când rezolvați un conflict).

Abordarea obișnuită în timpul dezvoltării este

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

Când ești gata să fuzionezi din nou în master,

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

Dacă sunteți îngrijorat că nu veți sparge ceva la îmbinare, git merge --abort este acolo pentru dvs.

Este o prostie să folosești împingerea și apoi tragerea ca mijloc de îmbinare. De asemenea, nu sunt sigur de ce împingeți testul la origine.

person raylu    schedule 10.04.2011
comment
Acest proces va crește numărul de comiteri, de fiecare dată când comutați între ramuri, trebuie să vă comiteți ramurile. - person iBug; 21.07.2014
comment
Ce? Vrei să spui că va crește numărul de comiteri de fiecare dată când schimbi ramuri? Sau spui că de fiecare dată când schimbi sucursala, trebuie să-ți angajezi sucursala? Prima este neadevărată și nu sunt sigur ce înseamnă a doua. - person raylu; 21.07.2014
comment
înainte de checkout, trebuie să comiți ramura. asta spun eu - person iBug; 22.07.2014
comment
Tu nu: asta e (unul dintre lucruri) git stash este pentru. - person msanford; 13.08.2014
comment
Aș recomanda git checkout test; git pull în loc de git merge origin/test. Chiar mai bine este git pull --rebase. Oricum, ai uitat să tragi modificările, așa că înainte de git merge origin/test ar trebui să git fetch origin test (git fetch .. && git merge .. este exact ceea ce face git pull .. :)) - person KingCrunch; 25.12.2015
comment
În teorie, dacă test este la o altă telecomandă decât master, da. Dar, din moment ce, în general, aveți o singură telecomandă, tragerea o dată le actualizează pe ambele și apoi puteți pur și simplu să îmbinați (sau să rebazați). - person raylu; 27.12.2015
comment
Sau ați putea să vă modificați ultimul commit (în filiala locală) și să îl faceți cel perfect înainte de a împinge. - person whihathac; 14.04.2016

Mai întâi aș face ramura care urmează să fie îmbinată cât mai curată posibil. Rulați-vă testele, asigurați-vă că starea este așa cum doriți. Curățați noile comenzi prin git squash.

Pe lângă Răspunsul KingCrunches, vă sugerez să utilizați

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

S-ar putea să fi făcut multe comiteri în cealaltă ramură, care ar trebui să fie doar un comit în ramura principală. Pentru a menține istoricul de comitere cât mai curat posibil, s-ar putea să doriți să strângeți toate comitările din ramura de testare într-un singur comit în ramura principală (consultați și: Git: To squash or not to squash?). Apoi, puteți și rescrie mesajul de confirmare la ceva foarte expresiv. Ceva care este ușor de citit și de înțeles, fără să pătrundă în cod.

edit: S-ar putea să te intereseze

Deci, pe GitHub, ajung să fac următoarele pentru o ramură de caracteristică mybranch:

Obțineți cele mai recente de la origine

$ git checkout master
$ git pull origin master

Găsiți hashul de bază de îmbinare:

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

Acum asigurați-vă că numai primul este pick, restul este s:

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

Apoi alegeți un mesaj de confirmare foarte bun și apăsați în GitHub. Atunci faceți cererea de tragere.

După îmbinarea cererii de extragere, o puteți șterge local:

$ git branch -d mybranch

și pe GitHub

$ git push origin :mybranch
person Martin Thoma    schedule 21.04.2016
comment
care ar trebui să fie doar un comit în ramura principală, ei bine, nu neapărat; ați putea dori să păstrați istoria - person Cocowalla; 12.04.2018
comment
Sigur. Dar atunci pur și simplu nu strivi comit-urile - person Martin Thoma; 12.04.2018
comment
Cred că --primul părinte pare a fi cea mai bună soluție. davidchudzicki.com/posts/first-parent - person bkribbs; 21.09.2018

Subiect vechi, dar nu am găsit modul meu de a o face. Ar putea fi valoros pentru cineva care lucrează cu rebase și dorește să îmbine toate commit-urile dintr-o ramură (funcție) deasupra masterului. Dacă există un conflict pe drum, le puteți rezolva pentru fiecare comitere. Păstrați controlul deplin în timpul procesului și puteți anula oricând.

Aflați la curent cu Master și Filială:

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

Îmbinați sucursala peste Master:

git checkout <branch_name>
git rebase master

Opțional: dacă întâmpinați conflicte în timpul rebazei:

În primul rând, rezolvați conflictul în dosar. Apoi:

git add .
git rebase --continue

Puteți anula rebazarea oricând cu:

git rebase --abort

Impingeți-vă Sucursala rebazată:

git push origin <branch_name>

Dacă aveți această ramură împinsă înainte, trebuie să o depășiți cu o împingere forțată:

git push origin -f <branch_name>

Înainte de a face acest lucru, verificați întotdeauna dacă filiala dvs. locală actuală corespunde așteptărilor dvs., deoarece forțarea o înlocuiește pe cea veche din depozitul de la distanță.

Acum aveți două opțiuni:

  • A) Creați un PR (de exemplu, pe GitHub) și îmbinați-l acolo prin interfața de utilizare
  • B) Reveniți pe linia de comandă și îmbinați ramura în master
git checkout master
git merge --no-ff <branch_name>
git push origin master

Terminat.

person Robin Wieruch    schedule 31.10.2018
comment
Îmi place și așa. Un lucru pe care ați uitat să-l menționați este că deseori trebuie să forțați să vă împingeți ‹branch_name› după ce vă rebazați. - person kenecaswell; 30.03.2021

Acesta este fluxul de lucru pe care îl folosesc la locul meu de muncă cu echipa. Scenariul este așa cum ați descris. În primul rând, când am terminat de lucrat la test, rebazez cu master pentru a extrage orice a fost adăugat la master în timpul cât am lucrat la ramura test.

git pull -r upstream master

Acest lucru va trage modificările la master de când ați bifurcat ramura test și le va aplica, apoi va aplica modificările pe care le-ați făcut pentru a testa „pe deasupra” stării curente a masterului. Pot exista conflicte aici, dacă celelalte persoane au făcut modificări la aceleași fișiere pe care le-ați editat în test. Dacă există, va trebui să le remediați manual și să le efectuați. Odată ce ați făcut asta, veți fi bine să treceți la ramura principală și să îmbinați test fără probleme.

person djheru    schedule 16.03.2016

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

După îmbinare, dacă fișierul este modificat, atunci când îmbinați, acesta va apărea printr-o eroare de „Rezolvare conflict”

Deci, mai întâi trebuie să-ți rezolvi toate conflictele, apoi trebuie să comiți din nou toate modificările și apoi să împingi

git push origin master

Este mai bine să facă cine a făcut modificări în ramura de testare, pentru că știa ce modificări a făcut.

person Vinay Sikarwar    schedule 07.04.2015

Aș folosi metoda rebase. Mai ales pentru că reflectă perfect cazul tău din punct de vedere semantic, de exemplu. ceea ce doriți să faceți este să reîmprospătați starea ramurii dvs. actuale și să vă „prefaceți” ca și cum s-ar fi bazat pe cea mai recentă.

Deci, fără măcar să verific master, aș:

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

Desigur, doar preluarea de la origine nu reîmprospătează starea locală a master-ului dvs. (deoarece nu efectuează o îmbinare), dar este perfect ok pentru scopul nostru - vrem să evităm schimbarea, de dragul economisirii de timp.

person user776686    schedule 13.09.2018

Răspunsul lui @KingCrunch ar trebui să funcționeze în multe cazuri. O problemă care poate apărea este că este posibil să vă aflați pe o altă mașină care trebuie să extragă cele mai recente din test. Așadar, recomand să faci testul de tragere mai întâi. Revizia arată astfel:

git checkout test
git pull
git checkout master
git pull origin master
git merge test
git push origin master
person cgnorthcutt    schedule 28.02.2020

Voi răspunde conform ramurilor de dezvoltare și caracteristică,

dacă sunteți în ramura de caracteristici și trebuie să o actualizați cu develop, utilizați comenzile de mai jos:

git checkout develop
git pull
git checkout feature/xyz
git merge develop

Acum feature/xyz este actualizat cu ramura develop și vă puteți împinge modificările la feature/xyz de la distanță.

person omkar    schedule 20.05.2020

După cum spune titlul „Cel mai bun mod”, cred că este o idee bună să luați în considerare strategia de îmbinare a răbdare.

De la: https://git-scm.com/docs/merge-strategies

Cu această opțiune, „merge-recursive” petrece puțin timp în plus pentru a evita îmbinările greșite care apar uneori din cauza liniilor de potrivire neimportante (de exemplu, acolade de la funcții distincte). Folosiți-l atunci când ramurile care urmează să fie îmbinate s-au divergent în mod sălbatic. Vezi și git-diff[1] --patience.

Utilizare:

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

Git Alias

Folosesc întotdeauna un alias pentru asta, de ex. alerga o data:

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

Acum ai putea face:

git fetch
git pmerge origin/master
person Julian    schedule 16.11.2019

Trebuie să verificați ramura pentru a trage, deoarece tragerea înseamnă fuzionarea în master și aveți nevoie de un arbore de lucru pentru a se îmbina.

git checkout master
git pull

Nu este nevoie să verificați mai întâi; rebase face ceea ce trebuie cu două argumente

git rebase master test  

git checkout master
git merge test

git push împinge în mod implicit toate ramurile care există aici și pe telecomandă

git push
git checkout test
person Masoud Mokhtari    schedule 15.11.2019

Acesta este de la GitLab: trebuie doar să urmați instrucțiunile:

introduceți descrierea imaginii aici

person shdr    schedule 05.12.2019
comment
În step-1, verificați o ramură a caracteristicilor și apoi în step-2 verificați din nou ramura principală. Sunt confuz, de ce să verific ramura caracteristică în primul rând ?? Te rog explica - person Muhammad Tariq; 17.01.2021
comment
Se datorează faptului că, în acest scenariu, este prima dată preluarea din ramura caracteristică de origine (la distanță). după aceea, pentru a îmbina caracteristica cu master, trebuie să verificați master și să îmbinați caracteristica cu aceasta. - person shdr; 18.01.2021
comment
Apoi, în primul caz, git fetch origin feature nu ar trebui să fie a doua comandă după ce ați verificat ramura funcției de la distanță pentru a sincroniza local cu caracteristica de la distanță? - person Muhammad Tariq; 18.01.2021

Primesc întotdeauna conflicte de îmbinare când fac doar git merge feature-branch. Acest lucru pare să funcționeze pentru mine:

git checkout -b feature-branch

Faceți o grămadă de modificări de cod...

git merge -s ours master 
git checkout master
git merge feature-branch

or

git checkout -b feature-branch

Faceți o grămadă de modificări de cod...

git checkout master
git merge -X theirs feature-branch
person mchavezi    schedule 27.09.2020