Creating merge conflict
For sake of the demo, I'll use remote git repo, and locally cloned repos on 2 different instances. I'll make changes in python's simple server script. The base is
... #Handler for the GET requests def do_GET(self): if self.path=="/": self.path="/home.html" if self.path=="/command/": self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() # Send the html message self.wfile.write("transfer +79000000000") return ... try: #Create a web server and define the handler to manage the #incoming request server = HTTPServer(('', PORT_NUMBER), myHandler) print('Started httpserver on port ' , PORT_NUMBER)
And now I make changes on instance1:
- self.wfile.write("transfer +79000000000") + self.wfile.write("transfer +81500000000") ... - print('Started httpserver on port ' , PORT_NUMBER) + print('Run httpserver on port ' , PORT_NUMBER)
Then I commit and push this changes to remote.
Similarly, I make changes on local repo on instance2:
- # Send the html message - self.wfile.write("transfer +79000000000") + # transfer to Arthur's celluar phone + self.wfile.write("transfer +79111111111") ... - print('Started httpserver on port ' , PORT_NUMBER) + print('Started httpserver on port %s' % PORT_NUMBER)
Then I commit these changes, and try to push, and get expected error:
$ git push origin temp-branch-for-demo To gitlab.com:arthur-s/helper_scripts.git ! [rejected] temp-branch-for-demo -> temp-branch-for-demo (fetch first) error: failed to push some refs to 'email@example.com:arthur-s/helper_scripts.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.
So, git says that I should pull changes from remote. I pull changes, and get conflict:
$ git pull origin temp-branch-for-demo remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 2), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From gitlab.com:arthur-s/helper_scripts * branch temp-branch-for-demo -> FETCH_HEAD bf69429..10d3974 temp-branch-for-demo -> origin/temp-branch-for-demo Auto-merging python2-simple-server.py CONFLICT (content): Merge conflict in python2-simple-server.py Automatic merge failed; fix conflicts and then commit the result.
How to resolve this conflict?
Conflict is a part of code, where SCM (git) cannot univocally determine which changes to use in merging file. In my case, I made changes on same parts of code
python2-simple-server.py and see this for first conflicting part:
<<<<<<< HEAD # transfer to Arthur's celluar phone self.wfile.write("transfer +79111111111") ======= # Send the html message self.wfile.write("transfer +81500000000") >>>>>>> 10d39749eac26d53652df5c190927479c2bc34ec
So, here in the code I have uncertainty, git don't know what to choose - simply saying, transfer to
+79111111111 or to
And I need to choose myself, which part to use, or maybe totally override this section. I can manually remove
>>>>>>>, and edit content between this brackets. There's a merge tools, and I want to tell about my favorite ones.
Sublime Merge is a powerfull merge tool, intuitively understandable and with good UI. It has free and commercial versions. Free version comes with light theme only, paid version has light and dark themes.
VScode has integrated merge tool, also powerfull and with good UI.
Recently I openned for myself
vimdiff, and very liked it. To work with this tool need to know
vim basics, especially how to navigate between splitted windows (
w + one of navigation keys. Navigation keys are
Make vimdiff as default git merge tool:
git config merge.tool vimdiff git config merge.conflictstyle diff3 git config mergetool.prompt false
There's 2 options for conflictstyle -
merge, which is default option, and
diff3. Diff3 adds common ancestor in the view, it will be described below.
Now I may run conflict resolver as
At first glance this may be look ugly. But you may install attractive color schemas, and
vim will be very nice looking. Sublime merge and VSCode both splits window to 3 parts. Vimdiff splits it to 4 (with
diff3 configstyle), displaying common ancestor
On the screenshot, from left to right, there's file with LOCAL version, on center - BASE version (common ancestor), and 3rd is REMOTE version. Window on the bottom is file which will be MERGED.
Since vim is an editor, which designed to work with keyboard only, without mouse, you need to use this commands to choose which version to use in conflicting part of code. Move your cursor to the highlighted conflict area, and choose one of this versions:
:diffg RE " get from REMOTE :diffg BA " get from BASE :diffg LO " get from LOCAL
:diffg LO to use local changes.