This repo contains folders with small exercies. Each project has at least a README.md and a script (init.sh
) to set up the exercise.
The goal of this document and the exercises is to make you more comfortable using Git generally, and working with conflicts specifically.
I'll also be throwing in nice-to-knows and tips about good Git practises.
Please open issues and pull requests if you have questions or suggestions.
- How to use this
- Folder overview
- General info and tips
- Conflict resolution
- Tools
- Tutorials
- Windows users read this
cd
into a directory- Run
./init.sh
to initialize the example repository git branch
to see the two branches in the repogit merge <branch name>
to merge in changes from the feature branch into master- Solve the conflict! :)
All the folders will contain a README.md, which you should take a look at, and an init-script, which you must run to set up the exercise. Please read the section called "Windows users read this" if you use Windows.
-
mini The smallest possible conflict.
Here we learn how to abort a merge, and how to resolve it
by just editing the file. -
medium A small file with two conflicts. We learn to select one of the branches' version of history,
and use that as a starting point for resolving the conflict.
The next exercise will be a simple rebase. Stay tuned!
A conflict is a situation that arises when Git, or any other versioning tool for that matter, doesn't know what to do when joining two or more versions of a file.
Say you have a file that looks like this in the master
branch:
mad codez here
Then you create a feature
branch where you commit a change that makes the file look like this:
mad codez here
more codez
Then you create another branch, bugfix
, from master, and make the file look like this:
mad codez here
this is fix
If you then try to merge both feature
and bugfix
into master
, Git won't know what to do, and you will have
a conflict on line 2. Git will leave conflict markers and you will have to resolve the conflict, to tell Git
what to do.
If you merge in feature
first and then bugfix
, the conflicting file will look like this:
mad codez here
<<<<<<< HEAD
more codez
=======
this is fix
>>>>>>> bugfix
In this simple example it is trivial to just edit the file and commit it, but for larger conflicts, you might want to use a tool.
The simple answer is that Git doesn't always know how to merge multiple versions of a file. This happens when two different branches makes changes to the same place in the same file.
If two branches, say, a master
branch and a feature
branch, has a lot of different commits there is a possibillity
that merging the one into the other can result in a big, hairy conflict.
By updating either branch with the changes in the other regularly, you can get away with simple conflicts, if there are any.
A typical scenario is that you have a branch with some feature that you want to be somewhat finished before you introduce it
to the master branch. A good strategy to avoid difficult conflicts is to bring in changes from master
to your feature branch
regularly.
Updating your feature branch with changes from master can be done in a multitude of ways, but the two most popular are by merging and rebasing.
Merging are somewhat simpler and friendlier to beginners, and rebasing often produces cleaner history, which is a thing you should care about.
We recommend looking at tutorials to become familiar with the concepts. See the tutorials section.
When two commits change the same text it is sometimes usefull to know what the original text was.
Let's say you have this file on the master
branch:
Text from master branch
And the same file looking like this on the feature
branch:
Edit from feature branch
And in the bugfix
branch:
Edit from bugfix branch
Merging both into master would create this conflict (if feature was merged first):
<<<<<<< HEAD
Edit from feature branch
=======
Edit from bugfix branch
>>>>>>> bugfix
Now, if you had set the merge.conflictstyle
option in git to diff3
instead of the defaul merge
,
you could have had this:
<<<<<<< HEAD
Edit from feature branch
||||||| merged common ancestors
Text from master branch
=======
Edit from bugfix branch
>>>>>>> bugfix
This can be really helpfull if some or all the commits was made by someone else. We will use this conflict style in some of the examples.
You can set this option in a repo by doing git config merge.conflictstyle diff3
.
Toss in --global
if you would like it to always be like this. git config --global ...
When you have a conflict you can also check out a file in diff3 mode by doing
git checkout --conflict=diff3 filename
.
If you have experienced that setting this option breaks how tools for resolving conflicts works, please let me know.
When a conflict occurs, Git leaves conflict markers:
<<<<<<< HEAD
Some text
=======
Some other text
>>>>>>> bugfix
so it's easy to find the start, middle and end by searching for, respectively <<<<
, ====
and >>>>
,
in the file.
HEAD
here means that the change is in a commit on the current branch, and bugfix
is referring to the
branch you are merging from.
From this point Git doesn't care what the file looks like; you are free to git add
the file and commit it,
but that is probably not what you want to do.
A straight forward way of resolving the conflict would be to manually edit the file, and commit it when you are done.
For large and/or complicated conflicts, you might be better of using a tool. See the next section for links.
While Git has a great arsenal of tools for inspecting the history and different versions of a file, as well as for resolving conflicts, you might want to start of using a graphical interface of some sort. Tools like these let you select which parts you want to keep in a conflict, and some let's you edit the text directly.
Most of the ones listed here are full fledged Git interfaces, and some people do all their Git-work with one of them. I wouldn't say that these are better than using the terminal, or vice versa. As with everything else, different methods have different strengths and weaknesses. As one who understands how the different Git operations work, how they affect the history and what possibilities there are, I would recommend that you experiment both with using a client and the terminal. The clients/tools may help you understand concepts visually, and the terminal will give you a lot more power than anything else. You should also be somewhat comfortable with using the terminal as you won't always have a GUI to run your apps. Trust me, this will happen from time to time.
man giteveryday
- A useful minimum set of commands for Everyday Git
Online link
man gitworkflows
- An overview of recommended workflows with Git
Online link
-
Learn git branching An amazingly good place to go to get really comfortable working with Git.
You learn how to juggle commits back and forth between branches and remotes. This tutorial teaches you the concepts without using files. You just make commits and move them around. If you don't yet understand how commiting, merging, rebasing, fetching, pulling, pushing and cherry-picking works, AND what it does to your history, then this is definitely something to check out.
-
Try Git @ Code School A good intro to Git in the terminal. They cover the absolute basics in this free tutorial, but they have advanced courses as well. The advanced courses are paid courses, but you might be able to get a free trial.
-
Tutorialspoint A thorough walkthrough of most of the features Git provides.
The init-scripts used in the exercises is bash-scripts. These won't run on Windows. You may be able to read through them and create the repository yourself, but if someone wants to write setup-scripts for windows, it is very welcomed!