.
General Advice
Q: How to undo the modifications I made on one file?
Sometimes one may want to reverse the modifications done on one file. This may appear because the conflict on this file has been marked as solved (e.g., one only resolves with mergetool some of the conflicts in a file and then
git assumes that all conflicts have been solved) or that the assumptions made to solve the conflicts were wrong.
The command to revert the change made in a file <file> when resolving conflict is:
$ git checkout -- <filepath>
Q: What is an automatic merge commit and how to avoid those?
Automatic merge commits mess up with the changes history. Assume that while you were working on some feature in a separate branch, someone pushed a number of commits into the
master and currently the repo looks like:
HEAD
|
1 -> 2 -> 3 -> 4 -> 5 -> 6
\
`-> 4b -> 5b
After a
git pull you will have all commits in your repo, and in such case git usually creates an automatic merge that creates a new commit, such that 6->7 and 5b->7 (two parents).
HEAD
|
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
\ /
`-> 4b -> 5b -----`
Whereas with
git pull --rebase the merge commits could be avoided and the commit history would loks like:
1 -> 2 -> 3 -> 4 -> 5 -> 6 HEAD
\ |
`-> 4b -> 5b
Merging Branches Manually
This section describes some useful tips when merging branches in git.
Q: How can I reduce the number of merge conflicts? How can I ease future merges?
There is no magic. To avoid conlicts, reduce conflict zone size and ease conflict resolution one has to make their code easy to merge, even if it works in
master. To do so one should keep in mind that merge process works line by line (i.e. a line that has diverged in both branches is considered as conflict).
As merging branches is always more complicated than expected, consider again if a branch mybranch is really needed (e.g., if it can be replaced or combined with conditional compilation in C and Prolog to minimize the conflicts).
Q: How do I merge two branches?
To merge into a branch, your
HEAD should be at the branch you want to merge into. If you want to merge into
master a branch of yours with a lot of changes, you should first merge
master into your branch (resolve the potential conflicts) and then merge your branch in
master (it should have no conflict). When merging you should have no uncommitted modifications in your
HEAD, in general the cleaner your
HEAD is the smoother the merge will be.
E.g. To merge master into <mybranch> run:
$ get checkout <mybranch>
$ get merge master
Q: How to abort an uncommitted merge?
$ git reset --hard HEAD
Q: What do I do after resolving a merge conflict?
Before committing your merge (even if there is no conflict), you should verify that everything is going well. You should compile the project from scratch. For instance, one library/predicate used by specific code of your branch may have changed name/location in the master. Also run the tests.
If you do something else that just resolving syntactical conflicts, write details about those changes in the merge commit message.
Q: How do I rebase locally before a merge?
branch is the branch to be rebased and
target is the target branch (usually
master).
Warning: This process rewrites history, so do not run it unless you are sure no one else is using your branch and there are no branches starting at your branch. git fetch origin target; git merge origin/target is a less preferred alternative to this process.
- Make sure the current branch corresponds to the branch you want to rebase: git checkout branch.
- Fetch upstream changes: git fetch origin target.
- As we squash commits on merge anyway, we can do so when rebasing onto target too to reduce the number of conflicts to handle: git rebase --autostash -i origin/target (pick first and fixup rest).
- In order to allow the repository administrators to modify the commit message in GitLab, add an empty commit to the branch: git commit --allow-empty.
- Push changes: git push -v --force-with-lease origin branch