- Wat is een Git Merge Conflict?
- Soorten Merges
- Soorten Git Merge Conflicts
- Commando’s voor het Oplossen van Git Merge Conflicts
- Visuele Merge Tools
- Hoe los je een Git Merge Conflict op?
- Conclusie
Wat is een Git Merge Conflict?
Het Git versiebeheersysteem draait om samenwerken als een team en bijdragen aan projecten. Ontwikkelaars werken meestal op geïsoleerde branches en wanneer ze klaar zijn, voegen ze de wijzigingen samen met de hoofdbranch. Dit type samenwerking is zeer productief en effectief in het opsporen van bugs. Soms werken meerdere ontwikkelaars aan dezelfde regel code en wanneer ze proberen de wijzigingen samen te voegen, ontstaan er conflicten.
Eenvoudig Voorbeeld van een Git Conflict
Het diagram bovenaan geeft een perfect voorbeeld van hoe een typisch Git merge-conflict ontstaat. De hoofdbranch bevat een bestand met de tekst “HELLO, WORLD!”. De gebruikersnaam abid fork de hoofdbranch en wijzigt de tekst naar “HELLO, CAT!”. Terwijl abid wijzigingen aanbrengt, wordt de originele hoofdbranch ook aangepast naar “HELLO, DOG!”. Het samenvoegen van deze branches zal een merge-conflict veroorzaken en het proces stoppen.
De opdracht `git merge` heeft voornamelijk tot taak twee branches te combineren en de conflicten automatisch op te lossen. Soms echter komen conflicten bovendrijven waarbij twee personen dezelfde regel code hebben gewijzigd of essentiële bestanden hebben verwijderd die een andere ontwikkelaar aan het werk had. Git markeert deze wijzigingen en stopt het fusieproces. In dit geval kan het conflict niet automatisch worden opgelost; de ontwikkelaar moet de wijzigingen handmatig aanbrengen of hulpmiddelen gebruiken om het conflict op te lossen.
Merge Types
Git merge en rebase zijn twee manieren om commits van de doelbranch naar de bronbranch te integreren. Bovendien voert Git merge een fast-forward of een no-fast-forward merge uit. Als de top van de doelbranch in de bronbranch bestaat, wordt standaard een fast-forward merge uitgevoerd, en als deze ontbreekt, een no-fast-forward merge. Git rebase is een ander type merge dat de commitgeschiedenis van de doelbranch herschikt.
Fast-forward Merge
Standaard gebruikt Git merge de fast-forward-methode om ontbrekende commits in de doelbranch integreren. Bijvoorbeeld, het wordt gebruikt om de lokale branch bij te werken vanuit een externe server met de pull-opdracht. Fast-forward veroorzaakt geen enkele fusieconflicten, aangezien Git deze niet zal toepassen als de kop van de doelbranch ontbreekt in de bronbranch.
Fast-forward-merge
Een fast-forward-merge wordt ook wel een drieweg- of ware merge genoemd. Het creëert een nieuwe commit op de doelbranch door integratie van veranderingen in zowel de bronbranch als de doelbranch. De veranderingen worden gemengd na de laatste gemeenschappelijke commit in beide branches. In ons geval, dat is na C. Dit type merge zal de Git merge conflict oproepen als de bronbranch in conflict is met de doelbranch. In het bovenstaande diagram, de merge commit (X) wordt gecreëerd door integratie van de bronbranch en de doelbranch, waarin K en E de ouders van de merge commit zijn.
Rebase
Git rebase is wat anders dan andere typen. Het veranderd de sequentie van de doelbranch commit geschiedenis. Het rebase integreert de bronbranch zodat de doelbranch alle veranderingen uit de bronbranch bevat, gevolgd door alle commits van de doelbranch na de laatste gemeenschappelijke commit. In ons geval is de laatste gemeenschappelijke commit C, terwijl D en E uit de bronbranch komen. De K* commit is hetzelfde als K met een andere commit ID. In plaats van C te linken, zal het naar E verwijzen. Net zoals bij een fast-forward-merge, als er compatibility issues zijn tussen de bron en de doelbranch, zal Git een probleem oproepen om conflicten op te lossen voordat de rebase wordt voltooid.
Soorten van Git Merge Conflicten
Er zijn twee typen Git-samengestelde conflicten: aan het begin en tijdens het samengestelde proces – Atlassian. In deze sectie zullen we over beide typen leren en de manieren om elk scenario op te lossen.
Aan het Begin van de Samenvoeging
Git samenvoegen zal aan het begin mislukken als er wijzigingen zijn in het werkende directory of staging area. Het mislukken aan het begin dient ter preventie van de wijzigingen door inkomende samengestelde commits overschreven te worden. Dit gebeurt door conflicten met lokale wijzigingen, niet met andere branches of ontwikkelaars. Om de lokale toestand stabiel te maken, kun je commando’s zoals git stash
, git commit
, git checkout
of git reset
gebruiken.
Tijdens de Samenvoeging
Een mislukking tijdens de samenvoeging betekent dat er een conflict is tussen de bron- en doel branch waar meerdere ontwikkelaars dezelfde bestanden hebben aangepast. Als de automatische samenvoeging mislukt, zal Git u vragen om problemen handmatig op te lossen. U kunt ook derdepartij tools gebruiken om u te assisteren bij het visualiseren en integreren van de wijzigingen.
Commando’s voor het Resolven van Git-Samengestelde Conflicten
In deze sectie zullen we diverse native commando’s leren om de Git-samengestelde conflicten te visualiseren en op te lossen.
Algemene Commando’s
Git status is het meest gebruikte commando om de status weer te geven van gewijzigde bestanden, staging area en commits. Tijdens het samengestelde proces wordt het gebruikt om conflicterende bestanden te identificeren.
git status
De Git log met het –merge argument produceert de lijst van commits die in conflict zijn met de bronbranch.
git log --merge
Standaard laat de git diff
optie de verschillen zien tussen niet-gecommiteerde wijzigingen en eerdere commits. Git diff wordt gebruikt om branches, commits en bestanden te vergelijken. Het is handig voor het voorkomen van toekomstige merge-conflicten.
git diff
Commando’s bij Merge Fouten bij het Begin
Checkout wordt gebruikt om wijzigingen ongedaan te maken of te switchen naar een nieuwe of oude branch.
git checkout
Git reset wordt gebruikt om wijzigingen in het werkstation en de staging-area ongedaan te maken.
git reset --mixed
Commando’s bij Conflicten tijdens de Merge
Het –abort argument stopt het merge-proces en maakt de wijzigingen ongedaan naar hun oorspronkelijke staat voordat de merge startte.
git merge --abort
Git reset wordt meestal gebruikt tijdens het merge-proces om de conflicterende bestanden terug te zetten naar hun oorspronkelijke staat.
git reset
Los Conflicten tussen Verwijderde-Gebruikte Bestanden op
Een Git conflict treedt op als je het bestand in de huidige branch hebt verwijderd en iemand anders het in een andere branch heeft gewijzigd. In dit geval kun je ofwel een bestand toevoegen en committen,
git add <filename>
ofwel je kunt het bestand verwijderen en committen.
git rm <filename>
Visuele Merge Tools
Hulpmiddelen voor samenvoegen zijn gebruiksvriendelijke visuele tools voor het identificeren en oplossen van alle soorten samenvoegconflicten. Sommige tools bieden extra mogelijkheden zoals het vergelijken van wijzigingen, Git-operaties en project- en repositorybeheer. Er zijn twee types Git-samenvoeghulpmiddelen: alleen terminalgebaseerd en op GUI gebaseerd. De terminalgebaseerde tools openen binnen PowerShell of Bash, en de GUI-gebaseerde tools openen in een venstermilieu.
Om de lijst met geïnstalleerde en geldige tools te controleren, gebruik:
git mergetool --tool-help
De lijst bestaat uit alle geldige tools die geïnstalleerd kunnen worden en geïntegreerd worden met git-opdrachten.
Bijvoorbeeld, we hebben vim en nvim standaard geïnstalleerd, en als je het verschil tussen een ongecommiteerd bestand en een eerdere commit wilt zien, typt:
git difftool --tool=vimdiff3
De vimdiff3-tool accentueert de wijzigingen en laat je commits binnen de terminal vergelijken.
Verschil Tussen Twee Versies van hetzelfde Bestand in Vimdiff3
Meld
Meld is een gratis en open-source tool dat het oplossen van samenvoegconflicten op een ander niveau brengt. Om het met Git te integreren, moet je eerst het programma downloaden en installeren vanaf de officiële website. Vervolgens voeg je het toe aan de globale configuratie zodat Git standaard Meld zal starten voor het oplossen van conflicten.
De onderstaande configuratieopdrachten zijn alleen van toepassing op Windows-gebruikers. De enige aanpassing die je moet maken is het pad naar het geïnstalleerde Meld-bestand voor Mac of Linux aanpassen.
git config --global merge.tool meld git config --global mergetool.meld.path "C:/Program Files (x86)/Meld/Meld.exe" git config --global diff.tool meld git config --global difftool.meld.path "C:/Program Files (x86)/Meld/Meld.exe"
Na het instellen van standaardwaarden kunt u git difftool
typen in de Git-lokale map om de Windows-versie van Meld te starten, of u kunt git mergetool
gebruiken om merge-conflicten op te lossen, zoals hieronder getoond.
Oplossen van een Merge-Conflict met Meld
VSCode
VSCode biedt de beste en meest populaire manier om merge-conflicten op te lossen. Wanneer Git niet in staat is bestanden automatisch te mergen, zal VSCode de conflictueuze code markeren en u vier opties geven: huidige wijzigingen accepteren, binnenkomende wijzigingen accepteren, beide wijzigingen accepteren en wijzigingen vergelijken. U kunt deze opties gebruiken om uw bestand schoon te maken en alle lopende kwesties op te lossen.
Oplossen van Merge-Conflict met VSCode
Als u op zoek bent naar een complete oplossing voor uw Git-operaties, probeer dan GitKraken. Het komt met een gratis client, een VSCode-extensie en biedt een ingebouwde tool voor het oplossen van merge-conflicten.
Hoe een Git-Merge-Conflict Oplossen
In deze sectie gaan we leren hoe we een Git-mergeconflict kunnen creëren en vervolgens oplossen. De tutorial is verdeeld in twee delen. In het eerste deel leren we Git-conflicten lokaal op te lossen; het tweede deel gaat over het oplossen van conflicten met een remote server (GitHub).
Lokale Merge Conflict
Het creëren van mergeconflicten zal ons helpen begrijpen hoe deze problemen in de eerste plaats ontstaan. Vervolgens kunnen we creatieve manieren gebruiken om deze problemen op te lossen of zelfs te voorkomen dat ze in de toekomst optreden.
We gaan nu een Git-repository maken met een enkel bestand en onze eerste commit maken om te beginnen.
- Maak een map aan genaamd datacamp.
- Verander de directory naar datacamp.
- Initialiseer Git.
- Maak een README.md-bestand met de gegeven titel.
- Stage en commit de wijzigingen in een bestand.
mkdir datacamp cd datacamp git init echo "# How to Resolve Git Merge Conflict" > README.md git add README.md git commit -m "first commit" >>> [main (root-commit) 8199ea2] first commit >>> 1 file changed, 1 insertion(+) >>> create mode 100644 README.md
Vervolgens maken we een nieuwe branch readme en veranderen de titel van “..Git Merge..” naar “..Git..”. Voeg het bestand toe en maak de commit met behulp van het -am argument.
git checkout -b readme echo "# How to Resolve Git Conflict" > README.md git commit -am "new branch conflict added" >>> [readme 155f694] new branch conflict added >>> 1 file changed, 1 insertion(+), 1 deletion(-)
Ga terug naar de main-branch en voeg een nieuwe regel toe aan het README.md-bestand met behulp van >>. Door de wijzigingen op te slaan en commits te maken, hebben we met succes een conflict gevormd tussen twee versies van hetzelfde bestand.
git checkout main echo "New change in base branch" >> README.md git commit -am " a line added to base branch Readme file" >>> [main f1f1874] a line added to base branch Readme file >>> 1 file changed, 1 insertion(+)
Zoals we kunnen zien, heeft Git bij het mergen van de readme-branch een bericht weergegeven waarin staat dat de automatische merge is mislukt en dat we handmatig wijzigingen moeten aanbrengen en vervolgens het resultaat moeten committen.
git merge readme >>> Auto-merging README.md >>> CONFLICT (content): Merge conflict in README.md >>> Automatic merge failed; fix conflicts and then commit the result.
Wij zullen het probleem handmatig oplossen door het bestand te openen en te bewerken in Notepad. Onderstaand plaatje toont een pijl met HEAD, een scheidingsteken, en een pijl in een andere richting met een readme. Het gedeelte met HEAD toont de bestaande wijzigingen in de hoofdbranch, en het gedeelte met readme is de branch die we willen samenvoegen, die bestaat uit een andere kop.
Handmatig een Merge Conflict Oplossen
Om het probleem op te lossen, zullen we het readme branch-gedeelte, de pijlen, en het scheidingsteken verwijderen. De definitieve versie van het bestand zou schoon moeten zijn, zoals hieronder weergegeven.
Conflict Opgelost
Nadat we het bestand hebben toegevoegd en een commit hebben gemaakt, is het merge conflict opgelost. Het is de meest voorkomende en eenvoudigste manier om problemen op te lossen. U kunt ook een geïntegreerde ontwikkelomgeving (IDE) gebruiken om problemen sneller op te lossen.
git commit -am "conflict resolved in file README.md" >>> [main 9994a29] conflict resolved in file README.md
Remote Merge Conflict
Om remote merge conflicts te maken en op te lossen, moeten we een nieuw repository op GitHub aanmaken.
Aanmaken van een Nieuwe Repository op GitHub
`
Volgende, voeg de naam van de externe opslag (origin) met het adres toe aan de repository en duw alle wijzigingen vanuit de lokale repository naar de externe hoofdbranch met behulp van upstream.
git remote add origin https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git git push --set-upstream origin main >>> Enumerating objects: 12, done. >>> Counting objects: 100% (12/12), done. >>> Delta compression using up to 4 threads >>> Compressing objects: 100% (6/6), done. >>> Writing objects: 100% (12/12), 998 bytes | 499.00 KiB/s, done. >>> Total 12 (delta 2), reused 0 (delta 0), pack-reused 0 >>> remote: Resolving deltas: 100% (2/2), done. >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> * [new branch] main -> main >>> branch 'main' set up to track 'origin/main'.
Om een conflict aan te maken, moeten we wijzigingen aanbrengen in de externe en lokale README.md-bestand. Je kunt de GitHub-bestandseditor gebruiken om “..Git merge..” naar “..Sit-Merge..” te veranderen en vervolgens de wijzigingen committen.
Wijzigingen maken in de GitHub Editor
Verander vervolgens in de lokale repository het README.md-bestand alleen maar door een eenvoudige titel toe te voegen en commit de wijzigingen.
echo "# How to Resolve Merge Conflicts in Git Tutorial" > README.md git commit -am "local branch changes in README.md" >>> [main c677a13] local branch changes in README.md >>> 1 file changed, 1 insertion(+), 4 deletions(-)
Ten slotte, duw de wijzigingen naar de externe server. Merk op dat Git een foutmelding heeft gegeven met hints over hoe het probleem op te lossen.
git push >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> ! [rejected] main -> main (fetch first) >>> error: failed to push some refs to 'https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git' >>> hint: Updates were rejected because the remote contains work that you do >>> hint: not have locally. This is usually caused by another repository pushing >>> hint: to the same ref. You may want to first integrate the remote changes >>> hint: (e.g., 'git pull ...') before pushing again. >>> hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Wij zullen de eenvoudigste hint volgen, die inhoudt het bestand van de externe server eerst op te halen voordat je het duwt.
Halen van het bestand is mislukt vanwege een merge-conflict in het README.md-bestand. We zouden het handmatig kunnen repareren met Notepad, maar deze keer zullen we gebruik maken van een visueel hulpmiddel tijdens dit proces.
git pull >>> remote: Enumerating objects: 5, done. >>> remote: Counting objects: 100% (5/5), done. >>> remote: Compressing objects: 100% (2/2), done. >>> remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 >>> Unpacking objects: 100% (3/3), 681 bytes | 75.00 KiB/s, done. >>> From https://github.com/kingabzpro/DataCamp-Git-Merge-Guide >>> aaf149d..49b7d14 main -> origin/main >>> Auto-merging README.md >>> CONFLICT (content): Merge conflict in README.md >>> Automatic merge failed; fix conflicts and then commit the result.
De merge-tool Meld zal conflicterende bestanden identificeren en ze weergeven in de Meld GUI-toepassing.
git mergetool >>> Merging: >>> README.md >>> Normal merge conflict for 'README.md': >>> {local}: modified file >>> {remote}: modified file
Er zijn drie kolommen: README_LOCAL_473.md, README.md, en README_LOCAL_473.md. Als je denkt dat de externe wijzigingen geldig zijn, klik dan op de zwarte pijl in de externe kolom; en als je lokale wijzigingen wilt behouden, klik dan op de zwarte pijl in de lokale kolom. Zo eenvoudig is het.
`
Conflict opgelost met behulp van mergetool Meld
Na het aanbrengen van wijzigingen, sla het bestand op en commit. Zoals je kunt zien, veroorzaakt het pushen van een bestand naar een externe server geen merge conflict fout.
git commit -am "remote main branch conflict resolved" git push >>> Enumerating objects: 16, done. >>> Counting objects: 100% (16/16), done. >>> Delta compression using up to 4 threads >>> Compressing objects: 100% (6/6), done. >>> Writing objects: 100% (10/10), 1.08 KiB | 550.00 KiB/s, done. >>> Total 10 (delta 2), reused 0 (delta 0), pack-reused 0 >>> remote: Resolving deltas: 100% (2/2), completed with 1 local object. >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> 49b7d14..8f5c3aa main -> main
We hebben zowel lokale als externe merge conflicten succesvol opgelost. Deze conflicten worden dagelijks behandeld door datawetenschappers en machine learning engineers. Om je vaardigheden in Git-operaties te verbeteren, volg een Introductie tot Git cursus.
Conclusie
Het oplossen van Git merge conflicten is een complexe en zeer risicovolle taak, aangezien je de software kunt breken door defecte code samen te voegen. Merge tools bieden een gebruiksvriendelijke omgeving met een veiligere manier om merge conflicten te detecteren en op te lossen. In deze tutorial hebben we geleerd waarom Git-conflicten optreden en hoe we ze kunnen oplossen. We hebben ook verschillende merge- en conflicttypen behandeld, handige Git-commando’s en visuele tools. In het laatste gedeelte hebben we een merge conflict gecreëerd en opgelost in een lokaal en een extern repository.
Als je nieuw bent in Git en wilt leren hoe het werkt, lees dan: Introductie tot Git en GitHub Zelfstudie.
Source:
https://www.datacamp.com/tutorial/how-to-resolve-merge-conflicts-in-git-tutorial