Tuesday, July 5, 2016

Git Tutorial 3-- Merge and keep local branches


For this tutorial, dev1 and dev2 will use “git merge” to syncup branches (local master with remote master, local branch with local master), and since they just moved from SVN to Git, old habits die hard, they will keep working on their local branch.

Day 1 end

This is the end of day 1, dev1 is ready to call a day, he is happy with this changes, and ready to push his changes to the remote (we will assume dev1 is almost the lucky one, and simplify his actions, in reality, everyone should take similar actions as dev2) :
git checkout master
git merge t1
git push -v --tags --set-upstream origin master:master



dev2 wants to do the same thing, he first syncs up his local master with the remote master:
git checkout master
git pull origin master


Bad luck, dev2 finds out his branch t2 has deviated from master. He needs to get his changes into master, so he merges t2 into master, and when he does this, he runs into the dreaded conflict:
git checkout master
git merge t2

Git tries to be smart, and performs an auto-merge, but it fails. Note, upon automerging failure, Git has changed your file in the working directory, here is the content of testf:


dev2 will need to manually resolve this conflict (and delete those markers <<<<<<< HEAD, =======, >>>>>>> t2), he can signal to Git that the conflict has been resolved, and commit again (you don’t need to do merge again, because you are still in the merge process):
git add testf
git commit

dev2 is happy and pushes his changes to remote:
git push -v --tags --set-upstream origin master:master


Day 2

dev1 and dev2 should have both deleted their local branch now that all the changes have been pushed to the remote repository, and all the histories are safely stored, but they choose to continue to use the local branches, and that means they need to syncup their local branch with the remote master. Check out the previous diagrams, t1 and t2 are behind the local master which is in sync with the remote master.

dev1 syncs his local branch with the remote master:
git checkout master
git pull origin master
git checkout t1
#!!!!here it doesn't conflict!
git merge master

And then he commits 2 changes to t1,
echo 't1-c3' >> testf; git add testf; git commit -m 't1-c3'
echo 't1-c4' >> testf1; git add testf1; git commit -m 't1-c4'

And merges t1 into local master and pushes his changes to the remote master:
git checkout master
git pull origin master
git merge t1
git push -v --tags --set-upstream origin master:master

In our script, dev2 is always the unlucky one. He doesn’t realize his local master is behind, and he continues to work on his t2:
git checkout t2
echo 't2-c3' >>  testf; git add testf; git commit -m 't2-c3'



Now he realizes his local master is behind, so he syncs up his local master with the remote, and then anxious to make sure his changes are based on the latest code, he merges master into his local t2 and runs into a confict:
git checkout master
git pull origin master
git checkout t2
git merge master


Running git status shows you:



So again dev2 needs to carefully resolve the conflict (be sure to check out each marked lines). He then commits again:
git add testf
git commit



dev2 thinks his work is not finished and is not ready to push to remote master, so he keeps working on t2:
echo 't2-c4' >>  testf; git add testf; git commit -m 't2-c4'

Day 3

The sun always smiles on dev1, and he commits 1 change to t1 and pushes to the remote master:
echo 't1-c5'>> testf; git add testf; git commit -m 't1-c5'
git checkout master
git pull origin master
git merge t1
git push -v --tags --set-upstream origin master:master


Back to our unlucky dev2, he is ready to push his changes. First, he syncs his local master to remote, and then merges t2 into local master and runs into a conflict:
git checkout master
git pull origin master
git merge t2




Poor dev2, he needs to resolve the conflict again.
git add testf
git commit

because he has spent so much time on resolving the conflict, before he pushes his local master to remote, he syncs up his local master with the remote just to be sure there are no changes made that overlap his changes:
git checkout master
git pull origin master
git push -v --tags --set-upstream origin master:master

Resulting diagram looks like this:



Lessons learned:
  1. There are multiple branches involved, you need to be careful which one you are working on (so it is more difficult for a developer to use with Git)
  2. Git does automerge, and when there are conflicts, Git updates your working directory files with markers (<<<<<<< HEAD, =======, >>>>>>>), be sure to check out them out and delete them. if you find these markers confusing, you can use external merge/diff tools, such as BeyondCompare.
  3. And it is true that it is much harder to use Git than SVN.

No comments:

Post a Comment