Wednesday, February 6, 2019

How to solve merge conflict with git merge

A git repository usually have a stable master branch for building the release artifacts, a development branch for collecting development checkins. The developers branch out bugfix and feature branches from develop branch.

At 1 pm, developer A branched out from develop a bugfix1 branch and developer B branched out feature1 branch from develop. At 2 pm, developer A merged bugfix1 branch back to develop. At 3 pm, developer B also try to merge feature1 branch back to develop. The merge failed, the reason is they both modified the same lines for the same file and git can not tell whose version to keep. This situation is called merge conflict.

merge conflict at node4
merge conflict at node4


To merge feature1 to develop, we use the following commands:
git checkout develop;
then
git merge feature1;

If the merge didn't success, the first thing we need to do is to issue
git merge --abort
on the develop branch to abort the merge. When you use bitbucket gui to create a pull request, the bitbucket do the "git merge --abort" for you on the develop branch automatically.

Next, we need to fix the feature1 branch so that the conflict won't be there when develop merge feature1 next time.

To do that, we use the following commands:
git checkout feature1;
git merge develop;

This time instead of merge feature into develop, we merge develop into feature instead. As you can tell, no matter which direction the merge goes, the conflict will be there. We need to manually modify the conflicted files then commit a new version into feature1 branch. During our merge, the git knows our feature1 version is later than the develop version. So when we checkout develop then merge feature1, the feature1 version will override the develop version, so the merge will success.

Finally you use to sync your local and remote repo for the develop branch.
git push origin develop;

This approach will create 3 logs in the develop branch after the merge: bugfix1 commit, feature1 commit, conflict resolving commit.

For the developers that use bitbucket and pull request to merge feature and bugfix branches to develop. They need to solved the conflict local for feature1 branch, then
git push origin feature1;

then use pull request in bitbucket for merging into develop branch.

The process is demonstrated in the following demo:

In the next post, we will introduce an alternative approach with git rebase.
=============

GIT>git clone https://github.com/tekgadg/Pong_sept_20_2D.git demorepo
Cloning into 'demorepo'...
remote: Enumerating objects: 6, done.
remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 6
Unpacking objects: 100% (6/6), done.
Checking connectivity... done.
GIT>cd demorepo/
GIT>git config --global user.email you@example.com
GIT>git config --global user.name "you"
GIT>git branch develop
GIT>git checkout develop
Switched to branch 'develop'
GIT>echo a > a.txt
GIT>ech b > b.txt
-bash: ech: command not found
GIT>echo b > b.txt
GIT>echo c > c.txt
GIT>git commit -am "develop base"
On branch develop
Untracked files:
a.txt
b.txt
c.txt

nothing added to commit but untracked files present
GIT>git status
On branch develop
Untracked files:
  (use "git add <file>..." to include in what will be committed)

a.txt
b.txt
c.txt

nothing added to commit but untracked files present (use "git add" to track)
GIT>git add .
GIT>git commit -m "develop base"
[develop 1a27b56] develop base
 3 files changed, 3 insertions(+)
 create mode 100644 a.txt
 create mode 100644 b.txt
 create mode 100644 c.txt
GIT>git branch feature1
GIT>git branch bugfix1
GIT>git branch
  bugfix1
* develop
  feature1
  master
GIT>git checkout bugfix1
Switched to branch 'bugfix1'
GIT>echo xyzcode >> a.txt
GIT>echo xyzcode >> b.txt
GIT>git rm c.txt
rm 'c.txt'
GIT>git diff
diff --git a/a.txt b/a.txt
index 7898192..8267385 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,2 @@
 a
+xyzcode
diff --git a/b.txt b/b.txt
index 6178079..5e2bb23 100644
--- a/b.txt
+++ b/b.txt
@@ -1 +1,2 @@
 b
+xyzcode
GIT>git commit -am "bugfix1 commit"
[bugfix1 570873c] bugfix1 commit
 3 files changed, 2 insertions(+), 1 deletion(-)
 delete mode 100644 c.txt
GIT>git checkout develop
Switched to branch 'develop'
GIT>git merge bugfix1
Updating 1a27b56..570873c
Fast-forward
 a.txt | 1 +
 b.txt | 1 +
 c.txt | 1 -
 3 files changed, 2 insertions(+), 1 deletion(-)
 delete mode 100644 c.txt
GIT>git status
On branch develop
nothing to commit, working directory clean
GIT>git checkout feature1
Switched to branch 'feature1'
GIT>echo xyznetwork >> a.txt
GIT>echo xyznetwork > b.txt
GIT>echo xyznetwork >> c.txt
GIT>git commit -am "feature1 commit"
[feature1 6efd19f] feature1 commit
 3 files changed, 3 insertions(+), 1 deletion(-)
GIT>git diff
GIT>git checkout develop
Switched to branch 'develop'
GIT>git merge feature1
CONFLICT (modify/delete): c.txt deleted in HEAD and modified in feature1. Version feature1 of c.txt left in tree.
Auto-merging b.txt
CONFLICT (content): Merge conflict in b.txt
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.
GIT>git diff
diff --cc a.txt
index 8267385,56bdbb4..0000000
--- a/a.txt
+++ b/a.txt
@@@ -1,2 -1,2 +1,6 @@@
  a
++<<<<<<< HEAD
 +xyzcode
++=======
+ xyznetwork
++>>>>>>> feature1
diff --cc b.txt
index 5e2bb23,c09e41c..0000000
--- a/b.txt
+++ b/b.txt
@@@ -1,2 -1,1 +1,6 @@@
++<<<<<<< HEAD
 +b
 +xyzcode
++=======
+ xyznetwork
++>>>>>>> feature1
* Unmerged path c.txt
GIT>git merge --abort
GIT>git checkout feature1
Switched to branch 'feature1'
GIT>git checkout develop
Switched to branch 'develop'
GIT>git diff
GIT>git checkout feature1
Switched to branch 'feature1'
GIT>git merge develop
CONFLICT (modify/delete): c.txt deleted in develop and modified in HEAD. Version HEAD of c.txt left in tree.
Auto-merging b.txt
CONFLICT (content): Merge conflict in b.txt
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.
a
GIT>git diff
xyznetwork
diff --cc a.txt
index 56bdbb4,8267385..0000000
--- a/a.txt
+++ b/a.txt
@@@ -1,2 -1,2 +1,6 @@@
  a
++<<<<<<< HEAD
 +xyznetwork
++=======
+ xyzcode
++>>>>>>> develop
diff --cc b.txt
index c09e41c,5e2bb23..0000000
--- a/b.txt
+++ b/b.txt
@@@ -1,1 -1,2 +1,6 @@@
++<<<<<<< HEAD
 +xyznetwork
++=======
+ b
+ xyzcode
++>>>>>>> develop
* Unmerged path c.txt
GIT>vi a.txt
GIT>vi b.txt
GIT>git rm c.txt
c.txt: needs merge
rm 'c.txt'
GIT>git diff
diff --cc a.txt
index 56bdbb4,8267385..0000000
--- a/a.txt
+++ b/a.txt
diff --cc b.txt
index c09e41c,5e2bb23..0000000
--- a/b.txt
+++ b/b.txt
@@@ -1,1 -1,2 +1,3 @@@
 +xyznetwork
+ b
+ xyzcode
GIT>git status
On branch feature1
You have unmerged paths.
  (fix conflicts and run "git commit")

Changes to be committed:

deleted:    c.txt

Unmerged paths:
  (use "git add <file>..." to mark resolution)

both modified:   a.txt
both modified:   b.txt

GIT>git commit -am "conflict resolve with merge"
[feature1 b863a0d] conflict resolve with merge
GIT>git checkout develop
Switched to branch 'develop'
GIT>git merge feature1
Updating 570873c..b863a0d
Fast-forward
 b.txt | 1 +
 1 file changed, 1 insertion(+)
GIT>git status
On branch develop
nothing to commit, working directory clean
GIT>git branch
  bugfix1
* develop
  feature1
  master
GIT>git branch --delete bugfix1 feature1
Deleted branch bugfix1 (was 570873c).
Deleted branch feature1 (was b863a0d).
GIT>git branch
* develop
  master
GIT>git log
commit b863a0d537b6201495e4a7169883f32180b07f0e
Merge: 6efd19f 570873c
Author: you <you@example.com>
Date:   Wed Feb 6 07:44:21 2019 -0500

    conflict resolve with merge

commit 6efd19f7745211562b3ad33d079c55aae6beeb43
Author: you <you@example.com>
Date:   Wed Feb 6 07:40:53 2019 -0500

    feature1 commit

commit 570873c48d0e69c6a45e9b7d5891c7c35937c300
Author: you <you@example.com>
Date:   Wed Feb 6 07:39:04 2019 -0500

    bugfix1 commit

commit 1a27b5688d18352f747e7eea7ada7c65aeb8e90c
Author: you <you@example.com>
Date:   Wed Feb 6 07:37:08 2019 -0500

    develop base

commit 40aac7d161dc232299f81ed7112b88986b5fbe39
Author: SeanShin <seanshin@RetOne.local>
Date:   Sun Jun 14 16:19:04 2015 -0700

    upload
GIT>

No comments:

Post a Comment

Why I stopped publishing blog posts as information provider

Now the AI can generate content. Does that mean the web publishing industry reaches the end? ChatGPT said: ChatGPT Not at all. While AI can ...