Merging Git Branches

From IntelliJ-Wiki

Jump to: navigation, search

Contents

Introduction

You need to merge when you have diverged branches and the changes made in them differ. Most often this happens as a result of update from a remote repository when you work in a team environment.

Branches can also diverge when you are using Git locally. Suppose you have a working application and want to add new functionality to it. To preserve the working application, you create an experimental branch where you develop new features. At the same time, you update the existing code in the main branch. One day you decide that it’s time to introduce the new features from the experimental branch to the existing functionality. As both branches have been updated since they forked, most likely conflicts will arise when you start merging.

Let’s see how IntelliJ IDEA helps to analyze differences and resolve conflicts during merge.

In this tutorial we will consider two use cases:

You have two diverged branches. Both of them are updated, but the updates are made in different files. No conflicts occur, the merge is made automatically.

You have two diverged branches. Both of them are updated and the updates are made in the same file.

What This Tutorial Is Not About

This tutorial does not teach you when you need to merge and which version to accept during conflict resolution. It shows how to perform these operations right in IntelliJ IDEA.

Prerequisites

  1. You are working with IntelliJ IDEA version 9 or higher.
  2. You are familiar with the basics of Git.
  3. Git 1.6.0 or higher is installed on your computer.
  4. The Git integration plugin is enabled and the location of the Git executable file is correctly specified on the Git page of the Settings dialog box.
  5. You have an IntelliJ IDEA project with one plain Java module without any additional technologies enabled. The project name is not significant. This tutorial will be illustrated by a project named git_merge.
  6. A local Git repository is initialized under the git_merge project root.
  7. The git_merge project root with all the folders under it is put under Git control.

Populating the Sample Project

Now that all the prerequisites are fulfilled, let’s populate our git_merge project. For the sake of simplicity, we will illustrate the merge scenarios on three plain text files.

First, let’s create a text folder to store the files in. Right-click the project root folder git_merge (1), point at New (2), then select Directory (3) on the context menu.

Image 1.

In the New Directory dialog box (Image 2), specify the name of the new folder, in our example it is text (1).

Image 2.

The Project tool window shows the updated project tree with the new folder. Now let’s create three sample text files in it. Right-click the text folder, point at New, select File on the context menu, and specify the file name in the New File dialog box. Then confirm putting the new file under Git control in the Add File to Git dialog box that opens.

So doing, create three files: A.txt, B.txt, and C.txt.

Now open the files in the editor and type the following contents in them:

A.txtAAA
B.txtBBB
C.txtCCC

Committing the Changes

Finally, we need to save the first revision of files to the local repository. Open the Changes tool window (Image 3), right-click the Default change list (1) that contains our files(3) A.txt, B.txt, and C.txt, and choose Commit Changes (2) on the context menu:

Image 3.

In the Commit Changes dialog box (Image 4) that opens, make sure the check boxes (1) next to all the three files are selected. Then type a description of the commit in the Comment text box (2). Finally, click Commit (3).

Image 4.

Now we have the starting point for illustrating various situations when merging is applied.

Merging Independent Changes in Two Branches

As the result of populating our project, we have three text files A.txt, B.txt, and C.txt. In the Git perspective, we have one default master branch. This is the main branch in your local repository, in other VCSs it is called trunk. The master branch contains one revision (commit).

In scenario 1 We Will

  1. Create a copy of master with the name task.
  2. Update A.txt in master and C.txt in task and commit the changes to the branches.
  3. Merge the changes from task to master.

Creating the task Branch

Git branches in IntelliJ IDEA are created in the Checkout dialog box. To access it, choose Version Control | Git | Checkout Branch on the main menu:

Image 5.

The Checkout dialog box (Image 6) that opens informs you that we are currently working with master (1).

In the Checkout drop-down list (2), specify the source branch to make a copy of. You can see that there is only one branch in our local repository, because the list contains only one item, master. Select it.

In the As new branch text box (3), specify the name of the branch to be created. In our example, type task. The Track branch check box (5) determines whether IntelliJ IDEA should “remember” who the parent of the new branch is. This check box is selected by default.

Image 6.

Finally, click Checkout (4) to have IntelliJ IDEA create a new branch task.

Updating the Files

Now, we need to update two different files in task and master.

First of all, let’s learn which branch we are currently working with. Choose Version Control | Git | Current Branch. The Current Branch dialog box (Image 7) shows that we are working with task. It is correct because IntelliJ IDEA created task last and switched to it.

Image 7.

It is correct because IntelliJ IDEA created task last and switched to it. According to our scenario, we are going to update the C.txt file in this branch.

Updating C.txt in task

First, open the C.txt file in the editor if the file is closed and type the following text on a new line:

     Scenario 1. File C.txt updated in task.

Second, commit the changes. Switch to the Changes tool window. You can see that the updated file C.txt is on the Default changelist. Select the Default node and choose Commit Changes on the context menu. In the Commit Changes dialog box, provide a description for the commit in the Comment text box, for example, type:

     Scenario 1. File C.txt updated in task.

That’s all with updating the file C.txt in task.

Updating A.txt in master

Let’s now switch to master to update it and commit the changes. IntelliJ IDEA supports switching between branches in the Checkout dialog box accessed through Version Control | Git | Checkout Branch on the main menu. When the Checkout dialog box opens (Image 8), it shows that your current branch (1) is task. Select master from the Checkout drop-down list (2) and click Checkout(3).

Image 8.

Now open the A.txt file in the editor if the file is closed and type the following text on a new line:

     Scenario 1. File A.txt updated in master.

Finally, to commit the changes, proceed as when committing changes to C.txt in task.

Merging the Branches

Now let’s merge the changes from task to master in the dedicated Merge Branches dialog box. To access it, choose Version Control | Git | Merge Branches on the main menu. The Merge Branches dialog box (Image 9.) opens showing that master is the current branch (1), which means that the results of merge will be applied to master.

Image 9.

Next, you need to specify the source branch to merge the changes from (Image 10). To do that, select the check box next to task (2) in the Branches to merge list (3):

Image 10.

Now let’s decide on the merge strategy (Image 11). As you can see, the Default (4) value is preselected in the Strategy drop-down list (5). This means that Git will analyze the situation, detect the number of branches to be merged, and apply the strategy which it uses by default in such environment. For example, Git uses the Recursive strategy as default in our case when two branches are involved. Let’s rely on Git and accept the suggested Default (4) value.

Image 11.

No conflicts are expected so we can commit the merge results without any check (Image 12). Make sure that the No commit check box (6) is cleared. In the type

     Commit 3: Scenario 1, merge task into master.

in the Commit Message text box (7).

Image 12.


Finally, click the Merge button (8).

Viewing Merge Results

Now let’s see what we have after the merge in master:

  • A.txt was updated in master and remains unchanged.
  • B.txt was not updated at all at also remains unchanged.
  • C.txt was updated in task and was not changed manually in master but code>master</code> shows the updated version of C.txt.

The Merge Info tab (Image 13) of the Version Control tool window also shows that during the merge (1) only one file was updated (2) and this file is C.txt (3):

Image 13.

You can view the full Git log in the Console tab of the Version Control tool window:

Image 14.

Merging Branches with Conflicts

Now let’s make different modifications in two files in master and task and merge task into master. In one file, these modifications will affect the same line. In the other file, they will be made in different lines.

The table below illustrates the changes in the files A.txt and B.txt in two branches, master and task:

Image 15.

In scenario 2 We Will

  1. Update the files in master and commit the changes.
  2. Update the files in task and commit the changes.
  3. Switch to master and merge the changes from task into master. This step includes resolving conflicts.

Updating the Files in master

After completing the first scenario, you are expected to be working with master. If you are not, switch to master (Version Control | Git | Checkout Branch).

  1. Update the file A.txt as shown in Image 15. The file should look as follows, with a blue marker in the left gutter area (1) next to the updated line:
    Image 16.
  2. Update the file B.txt as shown in Image 15. The file should look as follows, with a blue marker in the left gutter area (1) next to the updated line:
    Image 17.
  3. Commit the changes.

Updating the Files in task

  1. Switch to task (Version Control | Git | Checkout Branch).
  2. Update the file A.txt as shown in Image 15. The file should look as follows, with a blue marker in the left gutter area (1) next to the updated line:
    Image 18.
  3. Update the file B.txt as shown in Image 15. The file should look as follows, with a blue marker in the left gutter area (1) next to the updated line:
    Image 19.
  4. Commit the changes.

Merging the Changes

Now let’s merge the changes from task into master. We have deliberately updated the same files in different ways, so conflicts are expected. Let’s see how IntelliJ IDEA helps resolve them.

  1. Switch to master (Version Control | Git | Checkout Branch).
  2. Choose Version Control | Git | Merge Branches on the main menu. The Merge Branches dialog box opens (Image 20) showing that the merge will be applied to master because it is the current branch (1).
    Image 20.
  3. Specify the source branch to merge the changes from. To do that, select the check box next to task (2) in the Branches to merge list (3).
  4. Accept the Default (4) merge strategy to have Git apply the strategy which is default for the current environment. In our case, when two branches are involved, Git uses the Recursive merge strategy by default.
  5. You will need to check the merge results before committing, so select the No commit (5) check box.
  6. Click the Merge (6) button. IntelliJ IDEA examines the differences between files in two branches and detects conflicts. The problematic files are listed in the Files Merged with Conflicts dialog box where we will now resolve the detected conflicts.

Resolving Conflicts

Predictably, the Files Merged with Conflicts dialog box (Image 21) shows the files A.txt (1) and B.txt (2).

Image 21.

When you select a problematic file from the list, IntelliJ IDEA suggests three resolution strategies:

  • Accept the version from the current branch master and abandon the task version. To apply this strategy, click the Accept Yours button (3).
  • Accept the version from the branch task by clicking the Accept Theirs button (4).
  • View the conflicting lines and choose the appropriate variant, possibly making some necessary editing. To apply this strategy, click the Merge button (5).

The first two ways are obvious, so you can apply any of them to the file B.txt.

Select A.txt and click the Merge button. IntelliJ IDEA starts a dedicated merge tool and opens an interactive dialog box (Image 22) that consists of three panes:

  • The left-hand pane (1) shows the last committed revision (HEAD) of the file A.txt in the current branch master. This pane is read-only.
  • The right-hand pane (2) shows the HEAD revision of A.txt in task. This pane is also read-only.
  • The central pane (3) is intended for merging conflicting lines manually. Here you can accept the new version of a line from any of the two branches involved. If necessary, you can modify the accepted version because the pane is editable and provides full range of coding assistance, including code completion, formatting, quick fixes, inspections, and so on. Originally, the pane shows the HEAD-1 revision of A.txt in master.

To facilitate exploring the code, IntelliJ IDEA shows conflict numbering and highlights problematic lines in all three panes.

Image 22.

Now, it’s time to decide what we want to get finally. The numbers on Image 22 will help you follow the message. Let’s take line1 from task (5) and line2 from master (6). Line1 (6) will require less manual editing, so let’s accept the version from master<?code> to have the line2 (5) inserted automatically and then update line1.

On the left-hand pane (<code>master), click the Accept button File:accept_button.png (4). Image 23 below shows what we have got. The merge tool has inserted line2 (2) and updated line1 (1) in the central pane with line1 (3) from the left-hand pane.

Image 23.

The tool also informs you (Image 24) that all the conflicts have been resolved and suggests saving the merge result:

Image 24.

However, if you click the Save and Finish button (1) in the All Changes Processed dialog box (Image 24), IntelliJ IDEA will close the merge tool and you will have line1 from master while we decided to take line2 from task. So click Continue (2).

You are again in the merge tool (Image 25).

Image 25.

Switch to the right-hand pane, copy line1 (1), and replace the text in line1 on the central pane (2).

Now the merge result looks as follows (Image 26.):

Image 27.

Click the Apply button (1). IntelliJ IDEA saves the merged result, closes the merge tool, and brings you back to the editor.

Having done with the merge, you only need to commit the merge result (Image 28). The commit procedure is standard with the only difference: IntelliJ IDEA has automatically generated the default commit message (1). This message states that the commit contains the results of a merge procedure during which two conflicts occurred (2).

Image 28.

If necessary, add some information to the message and the click the Commit button (3).

Useful Links

Using Git Locally with IntelliJ IDEA

http://www.kernel.org/pub/software/scm/git/docs/user-manual.html

http://book.git-scm.com/3_basic_branching_and_merging.html

Personal tools