A 5 minute git-integration tutorial

, Marblehead, MA

Sometimes I have several unrelated changes in progress, and I want to use two or more of those changes simultaneously on an integration branch.

git merge works okay, but it has some shortcomings.

  • It puts the burden on me to remember which branches to merge, in what order.

  • If I choose to merge incremental changes to the feature branches into the integration branch, the history of the integration branch gets hard to read.

  • It’s difficult to remove a feature branch from the integration branch.

Enter, git-integration.

Initialize a repository, to experiment:

[mlm@macbook:~/tmp]
$ mkdir git-integration

[mlm@macbook:~/tmp]
$ git init
Initialized empty Git repository in /Users/mlm/tmp/.git/

(master)[mlm@macbook:~/tmp]
$ git commit --allow-empty -m 'An initial commit'
[master (root-commit) 549a25c] An initial commit

Create a feature branch, “branch-a”:

(master)[mlm@macbook:~/tmp]
$ git checkout -b branch-a master
Switched to a new branch 'branch-a'

(branch-a)[mlm@macbook:~/tmp]
$ git commit --allow-empty -m 'A commit on branch-a'
[branch-a fb103b5] A commit on branch-a

Create a second feature branch, “branch-b”:

(branch-a)[mlm@macbook:~/tmp]
$ git checkout -b branch-b master
Switched to a new branch 'branch-b'

(branch-b)[mlm@macbook:~/tmp]
$ git commit --allow-empty -m 'A commit on branch-b'
[branch-b 548176b] A commit on branch-b

Have a look at the commit graph:

(branch-b)[mlm@macbook:~/tmp]
$ git log --graph --oneline --decorate --topo-order --all
* 548176b (HEAD, branch-b) A commit on branch-b
| * fb103b5 (branch-a) A commit on branch-a
|/  
* 549a25c (master) An initial commit

Switch to the master branch:

(branch-b)[mlm@macbook:~/tmp]
$ git checkout master
Switched to branch 'master'

Create an integration branch, “integration-branch”:

(master)[mlm@macbook:~/tmp]
$ git integration --create integration-branch
Switched to branch 'integration-branch'
Integration branch refs/heads/integration-branch created.

Add feature branches to it in whatever order you’d like:

(integration-branch)[mlm@macbook:~/tmp]
$ git integration --add branch-a

(integration-branch)[mlm@macbook:~/tmp]
$ git integration --add branch-b

Have a look at the configured recipe for the integration branch:

(integration-branch)[mlm@macbook:~/tmp]
$ git integration --cat
base master

merge branch-a

merge branch-b

Build the integration branch from the configured recipe:

(integration-branch)[mlm@macbook:~/tmp]
$ git integration --rebuild
Resetting to base master...
Merging branch branch-a...
Already up-to-date!
Merging branch branch-b...
Already up-to-date!
Successfully re-integrated integration-branch.

Have a look at the commit graph, including the newly built integration branch. It’s based on “master”, and includes “branch-a” and “branch-b” in the recipe’s order.

(integration-branch)[mlm@macbook:~/tmp]
$ git log --graph --oneline --decorate --topo-order --all
*   9840c1b (HEAD, integration-branch) Merge branch 'branch-b' into integration-branch
|\  
| * 548176b (branch-b) A commit on branch-b
* |   e486320 Merge branch 'branch-a' into integration-branch
|\ \  
| |/  
|/|   
| * fb103b5 (branch-a) A commit on branch-a
|/  
* 549a25c (master) An initial commit
* f206029 (refs/insns/integration-branch) Update integration branch refs/heads/integration-branch
* 10cf0c0 Update integration branch refs/heads/integration-branch
* feaff78 Create integration branch refs/heads/integration-branch

Now, make things more interesting by adding a commit to “branch-a”:

(integration-branch)[mlm@macbook:~/tmp]
$ git checkout branch-a
Switched to branch 'branch-a'

(branch-a)[mlm@macbook:~/tmp]
$ git commit --allow-empty -m 'A 2nd commit on branch-a'
[branch-a c53cdd5] A 2nd commit on branch-a

Rebuilding the integration branch from the recipe is only one step:

(branch-a)[mlm@macbook:~/tmp]
$ git checkout integration-branch 
Switched to branch 'integration-branch'

(integration-branch)[mlm@macbook:~/tmp]
$ git integration --rebuild
Resetting to base master...
Merging branch branch-a...
Already up-to-date!
Merging branch branch-b...
Already up-to-date!
Successfully re-integrated integration-branch.

Now it includes the updated “branch-a” branch followed by “branch-b”.

(integration-branch)[mlm@macbook:~/tmp]
$ git log --graph --oneline --decorate --topo-order --all
*   2ad9596 (HEAD, integration-branch) Merge branch 'branch-b' into integration-branch
|\  
| * 548176b (branch-b) A commit on branch-b
* |   29ac930 Merge branch 'branch-a' into integration-branch
|\ \  
| |/  
|/|   
| * c53cdd5 (branch-a) A 2nd commit on branch-a
| * fb103b5 A commit on branch-a
|/  
* 549a25c (master) An initial commit
* f206029 (refs/insns/integration-branch) Update integration branch refs/heads/integration-branch
* 10cf0c0 Update integration branch refs/heads/integration-branch
* feaff78 Create integration branch refs/heads/integration-branch

Enjoyed reading this post? Discuss it on Reddit, or follow me on Twitter.