Saturday, March 9, 2019

Tech Notes:- How to selectively merge files from a git branch to master

People who work with git regularly especially with branches might encounter a situation where they want to merge specific files from one branch to another. Here I am explaining how I accomplished this

My Scenario

I have a master branch and a new branch called "observium". I wanted to merge a few files to the master branch. To demonstrate it I did a checkout of the master branch, created a file called sreedev.txt and then committed it.

[sudeep@dev ansible]$ git checkout master
Switched to branch 'master'

[sudeep@dev ansible]$ git status
# On branch master


[sudeep@dev ansible]$ vim sreedev.txt
I entered the text "This is a file from the main branch" and saved it

[sudeep@dev ansible]$ git commit -m "Added a new file for demonstrating selective file merge"
[master e3a1a33] Added a new file for demonstrating selective file merge
 1 file changed, 1 insertion(+), 2 deletions(-)

[sudeep@dev ansible]$ git push origin master
Counting objects: 5, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 324 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To git@bitbucket.org:sudeepkumarks/ansible.git
   6ffda3a..e3a1a33  master -> master

Now I did a git checkout of my branch observium


[sudeep@dev ansible]$ git checkout observium
Switched to branch 'observium'

Created a file with the same name sreedev and updated a similar content which will conflict with content in the main branch. The intention here is to show how we handle the conflict during the selective merge

[sudeep@dev ansible]$ git add sreedev.txt
[sudeep@dev ansible]$ git commit -m "Added a new file for demonstrating selective file merge"
[observium 04b5fa6] Added a new file for demonstrating selective file merge
 1 file changed, 1 insertion(+), 3 deletions(-)

How to merge the files

Now we will try to merge the files sreedev in observium branch to the main branch 

[sudeep@dev ansible]$ git checkout master
Switched to branch 'master'

[sudeep@dev ansible]$ git checkout --patch observium sreedev.txt
diff --git b/sreedev.txt a/sreedev.txt
index e7d96cb..fe3f28c 100644
--- b/sreedev.txt
+++ a/sreedev.txt
@@ -1,2 +1 @@
-This is a file from the main branch
-
+This is a file from the observium branch
Apply this hunk to index and worktree [y,n,q,a,d,/,e,?]?

Since there is a conflict its asking questions on resolving the conflicts. At this stage, you have the below options

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

If you press y, the line  "This is a file from the main branch" will be removed and the line "This is a  file from the observium branch" will be added. If you want to keep the first line and remove the second one which is from the observium branch, you can press e and make manual changes and save it like how you save files in vim editor.

Once you complete the changes by saving, it will go to the next hunk if there is any conflict. This will repeat until all the conflict in the file is resolved. Now the git status should show the file as modified and added for commit. 

[sudeep@dev ansible]$ git checkout --patch observium sreedev.txt
diff --git b/sreedev.txt a/sreedev.txt
index e7d96cb..fe3f28c 100644
--- b/sreedev.txt
+++ a/sreedev.txt
@@ -1,2 +1 @@
-This is a file from the main branch
-
+This is a file from the observium branch
Apply this hunk to index and worktree [y,n,q,a,d,/,e,?]? y

[sudeep@dev ansible]$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#       modified:   sreedev.txt
#
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#       master


Now you can commit the changes like normal to have the changes from Observium branch in your master branch. This can be followed for merging specific files from any branch.

Related Posts Plugin for WordPress, Blogger...