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 <<<<<<延伸文章資訊
- 1實戰版本衝突(Dealing with Conflict) - Practical guide for git users
git checkout --theirs <conflict file>. 上述的指令顧名思義就是把有衝突的檔案還原到對方的版本。 反之,如果要以我們自己的版本為準時,就可以改用--ours :.
- 2Advanced Merging - Git SCM
If you pass it diff3 , Git will use a slightly different version of conflict markers, not only gi...
- 3Strategies to resolve git conflicts using "theirs" and "ours"
You can use git merge --abort command to abort the merge process when a merge conflict has alread...
- 4git - ours vs theirs
Automatic merge failed; fix conflicts and then commit the result. either fix the conflict manuall...
- 5Fixing Git Merge Conflicts: Reference and Examples
Fix all conflicts using "their" changes