Is er een “hun” versie van “git merge -s ours”?

Bij het samenvoegen van topic branch “B” in “A” met behulp van git merge, krijg ik wat conflicten. Ik weet dat alle conflicten kunnen worden opgelost met de versie in “B”.

Ik ben op de hoogte van git merge -s ours. Maar wat ik wil is zoiets als git merge -s theirs.

Waarom bestaat het niet? Hoe kan ik hetzelfde resultaat bereiken na de conflicterende merge met bestaande git commando’s? (git checkout elk niet-samengevoegd bestand van B)

UPDATE: De “oplossing” van het weggooien van alles van branch A (het merge-commit point naar B-versie van de tree) is niet wat ik zoek.


Antwoord 1, autoriteit 100%

Voeg de optie -X toe aan theirs. Bijvoorbeeld:

git checkout branchA
git merge -X theirs branchB

Alles wordt op de gewenste manier samengevoegd.

Het enige dat ik problemen heb zien veroorzaken, is als bestanden uit branchB werden verwijderd. Ze verschijnen als conflicten als iets anders dan git de verwijdering heeft gedaan.

De oplossing is eenvoudig. Voer gewoon git rm uit met de naam van alle bestanden die zijn verwijderd:

git rm {DELETED-FILE-NAME}

Daarna zouden de -X theirs moeten werken zoals verwacht.

Natuurlijk zal het daadwerkelijke verwijderen met het git rm commando voorkomen dat het conflict zich in de eerste plaats voordoet.


Opmerking: Er bestaat ook een langere formulieroptie.

Om het te gebruiken, vervangt u:

-X theirs

met:

--strategy-option=theirs

Antwoord 2, autoriteit 20%

Een mogelijke en geteste oplossing voor het samenvoegen van branchB in onze uitgecheckte branchA:

# in case branchA is not our current branch
git checkout branchA
# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB    
# make temporary branch to merged commit
git branch branchTEMP         
# get contents of working tree and index to the one of branchB
git reset --hard branchB
# reset to our merged commit but 
# keep contents of working tree and index
git reset --soft branchTEMP
# change the contents of the merged commit
# with the contents of branchB
git commit --amend
# get rid off our temporary branch
git branch -D branchTEMP
# verify that the merge commit contains only contents of branchB
git diff HEAD branchB

Om het te automatiseren, kun je het in een script inpakken met branchA en branchB als argumenten.

Deze oplossing behoudt de eerste en tweede ouder van de merge-commit, net zoals je zou verwachten van git merge -s theirs branchB.


Antwoord 3, autoriteit 8%

Oudere versies van git stonden je toe om de “hun” samenvoegstrategie te gebruiken:

git pull --strategy=theirs remote_branch

Maar dit is inmiddels verwijderd, zoals uitgelegd in dit bericht door Junio ​​Hamano (de Git-beheerder). Zoals vermeld in de link, zou je in plaats daarvan dit doen:

git fetch origin
git reset --hard origin

Houd er echter rekening mee dat dit anders is dan een daadwerkelijke samenvoeging. Uw oplossing is waarschijnlijk de optie die u echt zoekt.


Antwoord 4, autoriteit 7%

Het is niet helemaal duidelijk wat je gewenste resultaat is, dus er is enige verwarring over de “juiste” manier om dit te doen in de antwoorden en hun opmerkingen. Ik probeer een overzicht te geven en zie de volgende drie opties:

Probeer samen te voegen en gebruik B voor conflicten

Dit is niet de “hun versie voor git merge -s ours” maar de “huns versie voor git merge -X ours” (wat een afkorting is voor git merge -s recursive -X ours):

git checkout branchA
# also uses -s recursive implicitly
git merge -X theirs branchB

Dit is wat b.v. Het antwoord van Alan W. Smith wel.

Alleen inhoud van B gebruiken

Dit creëert een merge-commit voor beide branches, maar negeert alle wijzigingen van branchA en behoudt alleen de inhoud van branchB.

# Get the content you want to keep.
# If you want to keep branchB at the current commit, you can add --detached,
# else it will be advanced to the merge commit in the next step.
git checkout branchB
# Do the merge an keep current (our) content from branchB we just checked out.
git merge -s ours branchA
# Set branchA to current commit and check it out.
git checkout -B branchA

Merk op dat de samenvoeging van de eerste ouder nu die is van branchB en alleen de tweede is van branchA. Dit is wat bijv. Het antwoord van Gandalf458 wel.

Gebruik alleen inhoud van B en behoud de juiste volgorde voor de ouders

Dit is de echte “hun versie voor git merge -s ours“. Het heeft dezelfde inhoud als in de vorige optie (dwz alleen die van branchB) maar de volgorde van de ouders is correct, dwz de eerste ouder komt van branchA en de tweede van branchB.

git checkout branchA
# Do a merge commit. The content of this commit does not matter,
# so use a strategy that never fails.
# Note: This advances branchA.
git merge -s ours branchB
# Change working tree and index to desired content.
# --detach ensures branchB will not move when doing the reset in the next step.
git checkout --detach branchB
# Move HEAD to branchA without changing contents of working tree and index.
git reset --soft branchA
# 'attach' HEAD to branchA.
# This ensures branchA will move when doing 'commit --amend'.
git checkout branchA
# Change content of merge commit to current index (i.e. content of branchB).
git commit --amend -C HEAD

Dit is wat het antwoord van Paul Pladijs doet (zonder dat er een tijdelijke branch nodig is).


Antwoord 5, autoriteit 6%

Ik gebruik sindsdien het antwoord van Paul Pladijs. Ik ontdekte dat je een “normale” samenvoeging kunt doen, er treden conflicten op, dus dat doe je

git checkout --theirs <file>

om het conflict op te lossen door de revisie van de andere branch te gebruiken. Als je dit voor elk bestand doet, heb je hetzelfde gedrag als je zou verwachten van

git merge <branch> -s theirs

Hoe dan ook, de inspanning is meer dan het zou zijn met de fusiestrategie! (Dit is getest met git versie 1.8.0)


Antwoord 6, autoriteit 2%

Bij het samenvoegen van topic branch “B” in “A” met behulp van git merge, krijg ik wat conflicten. Ik >weet dat alle conflicten kunnen worden opgelost met de versie in “B”.

Ik ben me bewust van git merge -s ours. Maar wat ik wil is zoiets als git merge >-s hun.

Ik neem aan dat je een branch van master hebt gemaakt en nu weer wilt mergen in master, waarbij je alle oude dingen in master overschrijft. Dat is precies wat ik wilde doen toen ik dit bericht tegenkwam.

Doe precies wat je wilt doen, behalve eerst de ene branch in de andere samenvoegen. Ik heb dit zojuist gedaan en het werkte prima.

git checkout Branch
git merge master -s ours

Kijk dan de master af en voeg je branch erin samen (het zal nu soepel gaan):

git checkout master
git merge Branch

Antwoord 7, autoriteit 2%

Ik heb mijn probleem opgelost met

git checkout -m old
git checkout -b new B
git merge -s ours old

Antwoord 8

Als je in tak A zit, doe dan:

git merge -s recursive -X theirs B

Getest op git-versie 1.7.8


Antwoord 9

Om echt een merge uit te voeren die alleen input nodig heeft van de branch die je merged, kun je dat doen

git merge --strategy=ours ref-to-be-merged

git diff --binary ref-to-be-merged | git apply --reverse --index

git commit --amend

Er zullen geen conflicten zijn in elk scenario dat ik ken, je hoeft geen extra branches te maken, en het werkt als een normale merge-commit.

Dit is echter niet leuk met submodules.


Antwoord 10

Waarom bestaat het niet?

Terwijl ik in “git-commando voor het maken van de ene branch als een andere” vermeld hoe git merge -s theirs, merk op dat Git 2.15 (Q4 2017) nu duidelijker is:

De documentatie voor ‘-X<option>‘ voor samenvoegingen was misleidend
geschreven om te suggereren dat “-s theirs” bestaat, wat niet het geval is.

Zie commit c25d98b (25 sep 2017) door Junio ​​C Hamano (gitster).
(Samengevoegd door Junio ​​C Hamano — gitster in commit 4da3e23, 28 sep 2017)

merge-strategieën: vermijd de suggestie dat “-s theirs” bestaat

De beschrijving van de -Xours samenvoegoptie heeft een opmerking tussen haakjes
dat vertelt de lezers dat het heel anders is dan -s ours,
wat correct is, maar de beschrijving van -Xtheirs die erop volgt
zegt achteloos “dit is het tegenovergestelde van ours“, met een false
indruk dat de lezers ook gewaarschuwd moeten worden dat het erg is
anders dan -s theirs, die in werkelijkheid niet eens bestaat.

-Xtheirs is een strategieoptie die wordt toegepast op recursieve strategieën. Dit betekent dat de recursieve strategie nog steeds alles samenvoegt wat het kan, en alleen terugvalt op “theirs“-logica in geval van conflicten.

Dat debat over de relevantie of niet van een theirs fusiestrategie werd onlangs weer teruggebracht in deze thread van september 2017.
Het erkent oudere (2008) discussies

Kortom, de vorige discussie kan worden samengevat als “we willen niet dat ‘-s theirs‘ is omdat het de verkeerde workflow aanmoedigt”.

Het vermeldt de alias:

mtheirs = !sh -c 'git merge -s ours --no-commit $1 && git read-tree -m -u $1' -

Yaroslav Halchenko probeert nogmaals voor die strategie te pleiten, maar Junio ​​C Hamano voegt toe:

De reden waarom de onze en die van hen niet symmetrisch zijn, is omdat jij jij bent en niet zij — de controle en eigendom van onze geschiedenis en hun geschiedenis is niet symmetrisch.

Als je eenmaal hebt besloten dat hun geschiedenis de hoofdlijn is, wil je liever je ontwikkelingslijn als een zijtak behandelen en een merge in die richting maken, dwz de eerste ouder van de resulterende merge is een commit op hun geschiedenis en de tweede ouder is de laatste slechte van je geschiedenis. Dus je zou uiteindelijk “checkout their-history && merge -s ours your-history” gebruiken om
houd het eerste ouderschap verstandig.

En op dat moment is het gebruik van “-s ours” niet langer een tijdelijke oplossing voor het ontbreken van “-s theirs“.
Het is een goed onderdeel van de gewenste semantiek, dwz vanuit het oogpunt van de overgebleven canonieke geschiedenis wil je behouden wat het deed, teniet doen wat de andere lijn van de geschiedenis deed.

Junio ​​voegt toe, zoals becommentarieerd door Mike Beaton:

git merge -s ours <their-ref> zegt in feite ‘markeer commits gemaakt tot <their-ref> op hun branch als commits om permanent te zijn genegeerd’;
en dit is van belang omdat, als je vervolgens samenvoegt vanuit latere staten van hun vertakking, hun latere wijzigingen zullen worden aangebracht zonder dat de genegeerde wijzigingen ooit worden aangebracht.


Antwoord 11

Zie het veel geciteerde antwoord van Junio ​​Hamano: als je gecommitteerde inhoud weggooien, gewoon de commits weggooien, of in ieder geval uit de hoofdgeschiedenis houden. Waarom zou je iedereen in de toekomst lastig vallen met het lezen van commit-berichten van commits die niets te bieden hebben?

Maar soms zijn er administratieve vereisten, of misschien een andere reden. Voor die situaties waarin je echt commits moet opnemen die niets bijdragen, wil je:

(edit: wow, heb ik dit eerder verkeerd gedaan. Deze werkt.)

git update-ref HEAD $(
        git commit-tree -m 'completely superseding with branchB content' \
                        -p HEAD -p branchB    branchB:
)
git reset --hard

Antwoord 12

Deze gebruikt een git sanitair commando read-tree, maar zorgt voor een kortere algehele workflow.

git checkout <base-branch>
git merge --no-commit -s ours <their-branch>
git read-tree -u --reset <their-branch>
git commit
# Check your work!
git diff <their-branch>

Antwoord 13

Ik denk dat je eigenlijk wilt:

git checkout -B mergeBranch branchB
git merge -s ours branchA
git checkout branchA
git merge mergeBranch
git branch -D mergeBranch

Dit lijkt onhandig, maar het zou moeten werken. Het enige dat ik echt niet leuk vind aan deze oplossing, is dat de git-geschiedenis verwarrend zal zijn… Maar de geschiedenis zal in ieder geval volledig bewaard blijven en je hoeft niets speciaals te doen voor verwijderde bestanden.


Antwoord 14

Het equivalent (dat de bovenliggende volgorde behoudt) van ‘git merge -s theirs branchB’

Vóór samenvoegen:voer hier de afbeeldingsbeschrijving in

!!! Zorg ervoor dat je in schone staat bent !!!

Voeg de samenvoeging toe:

git commit-tree -m "take theirs" -p HEAD -p branchB 'branchB^{tree}'
git reset --hard 36daf519952 # is the output of the prev command

Wat hebben we gedaan?
We hebben een nieuwe commit gemaakt waarvan twee ouders van ons en die van hen en het contnet van de commit is branchB – hun

Na samenvoegen:voer hier de afbeeldingsbeschrijving in

Precies:

git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'

Antwoord 15

Dit antwoord is gegeven door Paul Pladijs. Ik nam gewoon zijn commando’s over en maakte voor het gemak een git-alias.

Bewerk je .gitconfig en voeg het volgende toe:

[alias]
    mergetheirs = "!git merge -s ours \"$1\" && git branch temp_THEIRS && git reset --hard \"$1\" && git reset --soft temp_THEIRS && git commit --amend && git branch -D temp_THEIRS"

Dan kun je “git merge -s theirs A” uitvoeren door het volgende uit te voeren:

git checkout B (optional, just making sure we're on branch B)
git mergetheirs A

Antwoord 16

Hiermee wordt je nieuweBranch samengevoegd met de bestaande baseBranch

git checkout <baseBranch> // this will checkout baseBranch
git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch
git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch)
git checkout newBranch -- . //this will replace all conflicted files in baseBranch

Antwoord 17

Ik moest dit onlangs doen voor twee afzonderlijke opslagplaatsen die een gemeenschappelijke geschiedenis delen. Ik begon met:

  • Org/repository1 master
  • Org/repository2 master

Ik wilde dat alle wijzigingen van repository2 master werden toegepast op repository1 master, waarbij ik alle wijzigingen accepteerde die repository2 zou aanbrengen. In git’s termen, dit zou een strategie moeten zijn genaamd -s theirs MAAR het bestaat niet. Wees voorzichtig, want -X theirs heeft de naam alsof het is wat je wilt, maar het is NIET hetzelfde (het staat zelfs zo in de man-pagina).

De manier waarop ik dit oploste was om naar repository2 te gaan en een nieuwe branch repo1-merge te maken. In die branch heb ik git pull [email protected]:Org/repository1 -s ours uitgevoerd en het merget prima zonder problemen. Ik duw hem dan naar de afstandsbediening.

Vervolgens ga ik terug naar repository1 en maak ik een nieuwe branch repo2-merge. In die branch voer ik git pull [email protected]:Org/repository2 repo1-merge uit, wat zal eindigen met problemen.

Ten slotte zou je ofwel een samenvoegverzoek moeten indienen in repository1 om er de nieuwe master van te maken, of het gewoon als een branch houden.


Antwoord 18

Een eenvoudige en intuïtieve (naar mijn mening) manier om dit in twee stappen te doen is

git checkout branchB .
git commit -m "Picked up the content from branchB"

gevolgd door

git merge -s ours branchB

(wat de twee takken markeert als samengevoegd)

Het enige nadeel is dat het geen bestanden verwijdert die in branchB zijn verwijderd uit je huidige branch. Een eenvoudig verschil tussen de twee takken achteraf zal laten zien of er zulke bestanden zijn.

Deze aanpak maakt ook achteraf uit het revisielogboek duidelijk wat er is gedaan – en wat de bedoeling was.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

17 − four =

Other episodes