Advanced Merging - Git SCM
文章推薦指數: 80 %
If you pass it diff3 , Git will use a slightly different version of conflict markers, not only giving you the “ours” and “theirs” versions, but also the “base” ... About BranchingandMerging SmallandFast Distributed DataAssurance StagingArea FreeandOpenSource Trademark Documentation Reference Book Videos ExternalLinks Downloads GUIClients Logos Community Thisbookisavailablein English. Fulltranslationavailablein azərbaycandili, българскиезик, Deutsch, Español, Français, Ελληνικά, 日本語, 한국어, Nederlands, Русский, Slovenščina, Tagalog, Українська 简体中文, Partialtranslationsavailablein Čeština, Македонски, Polski, Српски, Ўзбекча, 繁體中文, Translationsstartedfor Беларуская, فارسی, Indonesian, Italiano, BahasaMelayu, Português(Brasil), Português(Portugal), Svenska, Türkçe. ThesourceofthisbookishostedonGitHub. Patches,suggestionsandcommentsarewelcome. Chapters▾ 1.GettingStarted 1.1 AboutVersionControl 1.2 AShortHistoryofGit 1.3 WhatisGit? 1.4 TheCommandLine 1.5 InstallingGit 1.6 First-TimeGitSetup 1.7 GettingHelp 1.8 Summary 2.GitBasics 2.1 GettingaGitRepository 2.2 RecordingChangestotheRepository 2.3 ViewingtheCommitHistory 2.4 UndoingThings 2.5 WorkingwithRemotes 2.6 Tagging 2.7 GitAliases 2.8 Summary 3.GitBranching 3.1 BranchesinaNutshell 3.2 BasicBranchingandMerging 3.3 BranchManagement 3.4 BranchingWorkflows 3.5 RemoteBranches 3.6 Rebasing 3.7 Summary 4.GitontheServer 4.1 TheProtocols 4.2 GettingGitonaServer 4.3 GeneratingYourSSHPublicKey 4.4 SettingUptheServer 4.5 GitDaemon 4.6 SmartHTTP 4.7 GitWeb 4.8 GitLab 4.9 ThirdPartyHostedOptions 4.10 Summary 5.DistributedGit 5.1 DistributedWorkflows 5.2 ContributingtoaProject 5.3 MaintainingaProject 5.4 Summary 6.GitHub 6.1 AccountSetupandConfiguration 6.2 ContributingtoaProject 6.3 MaintainingaProject 6.4 Managinganorganization 6.5 ScriptingGitHub 6.6 Summary 7.GitTools 7.1 RevisionSelection 7.2 InteractiveStaging 7.3 StashingandCleaning 7.4 SigningYourWork 7.5 Searching 7.6 RewritingHistory 7.7 ResetDemystified 7.8 AdvancedMerging 7.9 Rerere 7.10 DebuggingwithGit 7.11 Submodules 7.12 Bundling 7.13 Replace 7.14 CredentialStorage 7.15 Summary 8.CustomizingGit 8.1 GitConfiguration 8.2 GitAttributes 8.3 GitHooks 8.4 AnExampleGit-EnforcedPolicy 8.5 Summary 9.GitandOtherSystems 9.1 GitasaClient 9.2 MigratingtoGit 9.3 Summary 10.GitInternals 10.1 PlumbingandPorcelain 10.2 GitObjects 10.3 GitReferences 10.4 Packfiles 10.5 TheRefspec 10.6 TransferProtocols 10.7 MaintenanceandDataRecovery 10.8 EnvironmentVariables 10.9 Summary A1.AppendixA:GitinOtherEnvironments A1.1 GraphicalInterfaces A1.2 GitinVisualStudio A1.3 GitinVisualStudioCode A1.4 GitinIntelliJ/PyCharm/WebStorm/PhpStorm/RubyMine A1.5 GitinSublimeText A1.6 GitinBash A1.7 GitinZsh A1.8 GitinPowerShell A1.9 Summary A2.AppendixB:EmbeddingGitinyourApplications A2.1 Command-lineGit A2.2 Libgit2 A2.3 JGit A2.4 go-git A2.5 Dulwich A3.AppendixC:GitCommands A3.1 SetupandConfig A3.2 GettingandCreatingProjects A3.3 BasicSnapshotting A3.4 BranchingandMerging A3.5 SharingandUpdatingProjects A3.6 InspectionandComparison A3.7 Debugging A3.8 Patching A3.9 Email A3.10 ExternalSystems A3.11 Administration A3.12 PlumbingCommands 2ndEdition 7.8GitTools-AdvancedMerging AdvancedMerging MerginginGitistypicallyfairlyeasy. SinceGitmakesiteasytomergeanotherbranchmultipletimes,itmeansthatyoucanhaveaverylonglivedbranchbutyoucankeepituptodateasyougo,solvingsmallconflictsoften,ratherthanbesurprisedbyoneenormousconflictattheendoftheseries. However,sometimestrickyconflictsdooccur. Unlikesomeotherversioncontrolsystems,Gitdoesnottrytobeoverlycleveraboutmergeconflictresolution. Git’sphilosophyistobesmartaboutdeterminingwhenamergeresolutionisunambiguous,butifthereisaconflict,itdoesnottrytobecleveraboutautomaticallyresolvingit. Therefore,ifyouwaittoolongtomergetwobranchesthatdivergequickly,youcanrunintosomeissues. Inthissection,we’llgooverwhatsomeofthoseissuesmightbeandwhattoolsGitgivesyoutohelphandlethesemoretrickysituations. We’llalsocoversomeofthedifferent,non-standardtypesofmergesyoucando,aswellasseehowtobackoutofmergesthatyou’vedone. MergeConflicts WhilewecoveredsomebasicsonresolvingmergeconflictsinBasicMergeConflicts,formorecomplexconflicts,Gitprovidesafewtoolstohelpyoufigureoutwhat’sgoingonandhowtobetterdealwiththeconflict. Firstofall,ifatallpossible,trytomakesureyourworkingdirectoryiscleanbeforedoingamergethatmayhaveconflicts. Ifyouhaveworkinprogress,eithercommitittoatemporarybranchorstashit. Thismakesitsothatyoucanundoanythingyoutryhere. Ifyouhaveunsavedchangesinyourworkingdirectorywhenyoutryamerge,someofthesetipsmayhelpyoupreservethatwork. Let’swalkthroughaverysimpleexample. WehaveasupersimpleRubyfilethatprints'helloworld'. #!/usr/bin/envruby defhello puts'helloworld' end hello() Inourrepository,wecreateanewbranchnamedwhitespaceandproceedtochangealltheUnixlineendingstoDOSlineendings,essentiallychangingeverylineofthefile,butjustwithwhitespace. Thenwechangetheline“helloworld”to“hellomundo”. $gitcheckout-bwhitespace Switchedtoanewbranch'whitespace' $unix2doshello.rb unix2dos:convertingfilehello.rbtoDOSformat... $gitcommit-am'Converthello.rbtoDOS' [whitespace3270f76]Converthello.rbtoDOS 1filechanged,7insertions(+),7deletions(-) $vimhello.rb $gitdiff-b diff--gita/hello.rbb/hello.rb indexac51efd..e85207e100755 ---a/hello.rb +++b/hello.rb @@-1,7+1,7@@ #!/usr/bin/envruby defhello -puts'helloworld' +puts'hellomundo'^M end hello() $gitcommit-am'UseSpanishinsteadofEnglish' [whitespace6d338d2]UseSpanishinsteadofEnglish 1filechanged,1insertion(+),1deletion(-) Nowweswitchbacktoourmasterbranchandaddsomedocumentationforthefunction. $gitcheckoutmaster Switchedtobranch'master' $vimhello.rb $gitdiff diff--gita/hello.rbb/hello.rb indexac51efd..36c06c8100755 ---a/hello.rb +++b/hello.rb @@-1,5+1,6@@ #!/usr/bin/envruby +#printsoutagreeting defhello puts'helloworld' end $gitcommit-am'Addcommentdocumentingthefunction' [masterbec6336]Addcommentdocumentingthefunction 1filechanged,1insertion(+) Nowwetrytomergeinourwhitespacebranchandwe’llgetconflictsbecauseofthewhitespacechanges. $gitmergewhitespace Auto-merginghello.rb CONFLICT(content):Mergeconflictinhello.rb Automaticmergefailed;fixconflictsandthencommittheresult. AbortingaMerge Wenowhaveafewoptions. First,let’scoverhowtogetoutofthissituation. Ifyouperhapsweren’texpectingconflictsanddon’twanttoquitedealwiththesituationyet,youcansimplybackoutofthemergewithgitmerge--abort. $gitstatus-sb ##master UUhello.rb $gitmerge--abort $gitstatus-sb ##master Thegitmerge--abortoptiontriestorevertbacktoyourstatebeforeyouranthemerge. Theonlycaseswhereitmaynotbeabletodothisperfectlywouldbeifyouhadunstashed,uncommittedchangesinyourworkingdirectorywhenyouranit,otherwiseitshouldworkfine. Ifforsomereasonyoujustwanttostartover,youcanalsorungitreset--hardHEAD,andyourrepositorywillbebacktothelastcommittedstate. Rememberthatanyuncommittedworkwillbelost,somakesureyoudon’twantanyofyourchanges. IgnoringWhitespace Inthisspecificcase,theconflictsarewhitespacerelated. Weknowthisbecausethecaseissimple,butit’salsoprettyeasytotellinrealcaseswhenlookingattheconflictbecauseeverylineisremovedononesideandaddedagainontheother. Bydefault,Gitseesalloftheselinesasbeingchanged,soitcan’tmergethefiles. Thedefaultmergestrategycantakeargumentsthough,andafewofthemareaboutproperlyignoringwhitespacechanges. Ifyouseethatyouhavealotofwhitespaceissuesinamerge,youcansimplyabortitanddoitagain,thistimewith-Xignore-all-spaceor-Xignore-space-change. Thefirstoptionignoreswhitespacecompletelywhencomparinglines,thesecondtreatssequencesofoneormorewhitespacecharactersasequivalent. $gitmerge-Xignore-space-changewhitespace Auto-merginghello.rb Mergemadebythe'recursive'strategy. hello.rb|2+- 1filechanged,1insertion(+),1deletion(-) Sinceinthiscase,theactualfilechangeswerenotconflicting,onceweignorethewhitespacechanges,everythingmergesjustfine. Thisisalifesaverifyouhavesomeoneonyourteamwholikestooccasionallyreformateverythingfromspacestotabsorvice-versa. ManualFileRe-merging ThoughGithandleswhitespacepre-processingprettywell,thereareothertypesofchangesthatperhapsGitcan’thandleautomatically,butarescriptablefixes. Asanexample,let’spretendthatGitcouldnothandlethewhitespacechangeandweneededtodoitbyhand. Whatwereallyneedtodoisrunthefilewe’retryingtomergeinthroughados2unixprogrambeforetryingtheactualfilemerge. Sohowwouldwedothat? First,wegetintothemergeconflictstate. Thenwewanttogetcopiesofmyversionofthefile,theirversion(fromthebranchwe’remergingin)andthecommonversion(fromwherebothsidesbranchedoff). Thenwewanttofixupeithertheirsideoroursideandre-trythemergeagainforjustthissinglefile. Gettingthethreefileversionsisactuallyprettyeasy. Gitstoresalloftheseversionsintheindexunder“stages”whicheachhavenumbersassociatedwiththem. Stage1isthecommonancestor,stage2isyourversionandstage3isfromtheMERGE_HEAD,theversionyou’remergingin(“theirs”). Youcanextractacopyofeachoftheseversionsoftheconflictedfilewiththegitshowcommandandaspecialsyntax. $gitshow:1:hello.rb>hello.common.rb $gitshow:2:hello.rb>hello.ours.rb $gitshow:3:hello.rb>hello.theirs.rb Ifyouwanttogetalittlemorehardcore,youcanalsousethels-files-uplumbingcommandtogettheactualSHA-1softheGitblobsforeachofthesefiles. $gitls-files-u 100755ac51efdc3df4f4fd328d1a02ad05331d8e2c91111 hello.rb 10075536c06c8752c78d2aff89571132f3bf7841a7b5c32 hello.rb 100755e85207e04dfdd5eb0a1e9febbc67fd837c44a1cd3 hello.rb The:1:hello.rbisjustashorthandforlookingupthatblobSHA-1. Nowthatwehavethecontentofallthreestagesinourworkingdirectory,wecanmanuallyfixuptheirstofixthewhitespaceissueandre-mergethefilewiththelittle-knowngitmerge-filecommandwhichdoesjustthat. $dos2unixhello.theirs.rb dos2unix:convertingfilehello.theirs.rbtoUnixformat... $gitmerge-file-p\ hello.ours.rbhello.common.rbhello.theirs.rb>hello.rb $gitdiff-b diff--cchello.rb index36c06c8,e85207e..0000000 ---a/hello.rb +++b/hello.rb @@@-1,8-1,7+1,8@@@ #!/usr/bin/envruby +#printsoutagreeting defhello -puts'helloworld' +puts'hellomundo' end hello() Atthispointwehavenicelymergedthefile. Infact,thisactuallyworksbetterthantheignore-space-changeoptionbecausethisactuallyfixesthewhitespacechangesbeforemergeinsteadofsimplyignoringthem. Intheignore-space-changemerge,weactuallyendedupwithafewlineswithDOSlineendings,makingthingsmixed. Ifyouwanttogetanideabeforefinalizingthiscommitaboutwhatwasactuallychangedbetweenonesideortheother,youcanaskgitdifftocomparewhatisinyourworkingdirectorythatyou’reabouttocommitastheresultofthemergetoanyofthesestages. Let’sgothroughthemall. Tocompareyourresulttowhatyouhadinyourbranchbeforethemerge,inotherwords,toseewhatthemergeintroduced,youcanrungitdiff--ours: $gitdiff--ours *Unmergedpathhello.rb diff--gita/hello.rbb/hello.rb index36c06c8..44d0a25100755 ---a/hello.rb +++b/hello.rb @@-2,7+2,7@@ #printsoutagreeting defhello -puts'helloworld' +puts'hellomundo' end hello() Soherewecaneasilyseethatwhathappenedinourbranch,whatwe’reactuallyintroducingtothisfilewiththismerge,ischangingthatsingleline. Ifwewanttoseehowtheresultofthemergedifferedfromwhatwasontheirside,youcanrungitdiff--theirs. Inthisandthefollowingexample,wehavetouse-btostripoutthewhitespacebecausewe’recomparingittowhatisinGit,notourcleaneduphello.theirs.rbfile. $gitdiff--theirs-b *Unmergedpathhello.rb diff--gita/hello.rbb/hello.rb indexe85207e..44d0a25100755 ---a/hello.rb +++b/hello.rb @@-1,5+1,6@@ #!/usr/bin/envruby +#printsoutagreeting defhello puts'hellomundo' end Finally,youcanseehowthefilehaschangedfrombothsideswithgitdiff--base. $gitdiff--base-b *Unmergedpathhello.rb diff--gita/hello.rbb/hello.rb indexac51efd..44d0a25100755 ---a/hello.rb +++b/hello.rb @@-1,7+1,8@@ #!/usr/bin/envruby +#printsoutagreeting defhello -puts'helloworld' +puts'hellomundo' end hello() Atthispointwecanusethegitcleancommandtoclearouttheextrafileswecreatedtodothemanualmergebutnolongerneed. $gitclean-f Removinghello.common.rb Removinghello.ours.rb Removinghello.theirs.rb CheckingOutConflicts Perhapswe’renothappywiththeresolutionatthispointforsomereason,ormaybemanuallyeditingoneorbothsidesstilldidn’tworkwellandweneedmorecontext. Let’schangeuptheexamplealittle. Forthisexample,wehavetwolongerlivedbranchesthateachhaveafewcommitsinthembutcreatealegitimatecontentconflictwhenmerged. $gitlog--graph--oneline--decorate--all *f1270f7(HEAD,master)UpdateREADME *9af9d3bCreateREADME *694971dUpdatephraseto'holaworld' |*e3eb223(mundo)Addmoretests |*7cff591Createinitialtestingscript |*c3ffff1Changetextto'hellomundo' |/ *b7dcc89Initialhelloworldcode Wenowhavethreeuniquecommitsthatliveonlyonthemasterbranchandthreeothersthatliveonthemundobranch. Ifwetrytomergethemundobranchin,wegetaconflict. $gitmergemundo Auto-merginghello.rb CONFLICT(content):Mergeconflictinhello.rb Automaticmergefailed;fixconflictsandthencommittheresult. Wewouldliketoseewhatthemergeconflictis. Ifweopenupthefile,we’llseesomethinglikethis: #!/usr/bin/envruby defhello <<<<<<
>>>>>>mundo end hello() Bothsidesofthemergeaddedcontenttothisfile,butsomeofthecommitsmodifiedthefileinthesameplacethatcausedthisconflict. Let’sexploreacoupleoftoolsthatyounowhaveatyourdisposaltodeterminehowthisconflictcametobe. Perhapsit’snotobvioushowexactlyyoushouldfixthisconflict. Youneedmorecontext. Onehelpfultoolisgitcheckoutwiththe--conflictoption. Thiswillre-checkoutthefileagainandreplacethemergeconflictmarkers. Thiscanbeusefulifyouwanttoresetthemarkersandtrytoresolvethemagain. Youcanpass--conflicteitherdiff3ormerge(whichisthedefault). Ifyoupassitdiff3,Gitwilluseaslightlydifferentversionofconflictmarkers,notonlygivingyouthe“ours”and“theirs”versions,butalsothe“base”versioninlinetogiveyoumorecontext. $gitcheckout--conflict=diff3hello.rb Oncewerunthat,thefilewilllooklikethisinstead: #!/usr/bin/envruby defhello <<<<<<延伸文章資訊
- 1Quickest Way to Resolve Most Merge Conflicts - Git
Find files with merge conflict ... Change working directory to project folder. ... Search for all...
- 2Git: Handling Merge Conflicts Using "Ours" and "Theirs"
To resolve conflicts during a merge or rebase, we can use git checkout with one of two flags: --o...
- 3Fixing Git Merge Conflicts: Reference and Examples
Fix all conflicts using "their" changes
- 4Resolve Git merge conflicts in favor of their changes during a ...
git pull -X theirs creates a merge commit if there are conflicts (e.g. if another committer ran g...
- 5Use Theirs With Git Merge | Delft Stack
Use --strategy-option to Resolve Conflicts in Git