A 5 minute git-integration tutorial
, Marblehead, MASometimes 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