Showing posts with label GIT Conflicts. Show all posts
Showing posts with label GIT Conflicts. Show all posts

Friday, 28 December 2018

GIT: How to Integrate Branches

Separating different topics into different branches is a crucial practice for any serious developer. By not mixing up code from one feature / bugfix / experiment with another, you avoid a lot of problems - and don't have to worry about breaking things in your development branches.
But at some point your code will (hopefully) reach a state where you'll want to integrate it with the rest of the project. This is where the "git merge" command comes in.

A Simple Example

Let's assume a very simple example scenario:
Our goal is to integrate the changes from "contact-form" back into "master".

Preparing to Merge

Before merging your code into one of your project's long-running branches (like a "development" or "master" branch), make sure that your local repository is up to date. Both your local feature / bugfix / <topic> branch and the receiving branch should be updated with the latest changes from your remote server.
Start with a "git fetch", followed by a "git branch -va":
$ git fetch
...

$ git branch -va
  master             87eab46 [behind 1] Fix #332
* contact-form       b320ab3 Ensure safe login
The [behind 1] remark tells us that "master" has received new changes on the remote. We must update "master" before we can integrate our own changes.
If properly configured, a plain "git pull" should suffice (after making "master" our active branch):
$ git checkout master
$ git pull
The last thing to check before actually starting the merge process is our current HEAD branch: we need to make sure that we've checked out the branch that should receivethe changes.
But since we just updated "master" and already performed a "git checkout master", we're good to go!

Starting the Merge

With such perfect preparation, the actual merge process itself is easy as pie:
$ git merge contact-form
Looking at our project's commit history, we'll notice that a new commit was created: a so-called "merge commit" that represents the actual "melting knot" that combines the two branches.
Our integration was successful and, if our feature work on "contact-form" is finished, we could safely delete that branch.

Dealing with Conflicts

Git will do what it can to make merging as easy as in our example. And in many cases, a merge will indeed be a walk in the park.
In some cases, however, the integration will not go as smoothly: if the branches contain incompatible changes, you will have to face (and solve) a "merge conflict". If you want to learn more about how to handle such a situation, have a look at Dealing with Merge Conflicts.

Thursday, 27 December 2018

GIT: Solving merge conflicts

39.1. What is a conflict during a merge operation?

Merge conflict A conflict during a merge operation occurs if two commits from different branches have modified the same content and Git cannot automatically determine how both changes should be combined when merging these branches.
This happens for example if the same line in a file has been replaced by two different commits.
If a conflict occurs, Git marks the conflict in the file and the programmer has to resolve the conflict manually.
After resolving it, he adds the file to the staging area and commits the change. These steps are required to finish the merge operation.

GIT: Keep a version of a file during a merge conflict

Merge conflict LARSSECONDARY"theirs parameter"LARSSECONDARY Merge conflict
LARSSECONDARY"ours parameter"LARSSECONDARY Sometimes if a conflict occurs the developer does not want to solve the conflict. He decides that he wants to keep the original version or the new version of the file.
For this, there is the --theirs and the --ours options on the git checkout command. The first option keeps the version of the file that you merged in, and the second option keeps the version before the merge operation was started.
git checkout --ours foo/bar.java
git add foo/bar.java
git checkout --theirs foo/bar.java
git add foo/bar.java

GIT: Solving a conflict during a merge operation

41.1. Create a conflict

In the following example you create a conflict during a merge operation.
The following steps create a merge conflict. It assumes that repo1 and repo2 have the same origin repository defined.
# switch to the first directory
cd ~/repo01
# make changes
echo "Change in the first repository" > mergeconflict.txt
# stage and commit
git add . && git commit -a -m "Will create conflict 1"
# switch to the second directory
cd ~/repo02
# make changes
touch mergeconflict.txt
echo "Change in the second repository" > mergeconflict.txt
# stage and commit
git add . && git commit -a -m "Will create conflict 2"
# push to the master repository
git push
# switch to the first directory
cd ~/repo01

# now try to push from the first directory
# try to push --> assuming that the same remote repository is used,
# you get an error message
git push
As this push would not result in a non-fast-format merge, you receive an error message similar to the following listing.
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to '../remote-repository.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.
To solve this, you need to integrate the remote changes into your local repository. In the following listing the git fetchcommand gets the changes from the remote repository. The git merge command tries to integrate it into your local repository.
# get the changes via a fetch
git fetch origin

# now merge origin/master into the local master
# this creates a merge conflict in your
# local repository
git merge origin/master
This creates the conflict and a message similar to the following.
Auto-merging mergeconflict.txt
CONFLICT (add/add): Merge conflict in mergeconflict.txt
Automatic merge failed; fix conflicts and then commit the result.
The resulting conflict is displayed in ? and solved in ?
If you use the git pull command it performs the "fetch and merge" or the "fetch and rebase" command together in one step. Whether merge or rebase is used depends on your Git configuration for the branch. See ? for the global configuration.

41.2. Review the conflict in the file

Git marks the conflicts in the affected files. In the example from ? one file has a conflict and the file looks like the following listing.
<<<<<<< HEAD
Change in the first repository
=======
Change in the second repository
>>>>>>> b29196692f5ebfd10d8a9ca1911c8b08127c85f8
The text above the ======= signs is the conflicting change from your current branch and the text below is the conflicting change from the branch that you are merging in.

41.3. Solve a conflict in a file

In this example you resolve the conflict which was created in ? and apply the change to the Git repository.
To solve the merge conflict you edit the file manually. The following listing shows a possible result.
Change in the first and second repository
Afterwards add the affected file to the staging area and commit the result. This creates the merge commit. You can also push the integrated changes now to the remote repository.
# add the modified file
git add .

# creates the merge commit
git commit -m "Merge changes"

# push the changes to the remote repository
git push
Instead of using the -m option in the above example you can also use the git commit command without this option. In this case the command opens your default editor with the default commit message about the merged conflicts. It is good practice to use this message.
Alternatively, you could use the git mergetool command. git mergetool 
starts a configurable merge tool that displays the changes in a split screen. 
Some operating systems may come with a suitable merge tool already installed 
or configured for Git.

GIT: Solving rebase conflicts

42.1. What is a conflict during a rebase operation?

Rebase conflict During a rebase operation, several commits are applied onto a certain commit. If you rebase a branch onto another branch, this commit is the last common ancestor of the two branches.
For each commit which is applied it is possible that a conflict occurs.