Public:Git tips
From YaddaWiki
Contents |
Case with multiple branch pointers pointing at different parts of a common linear history
Incorporating changes from a separate branch
Before. We have a history like this:
b1 b2 | | \/ \/ a--b--c--d--e--f \-g--h /\ | b3
Where:
- There's a fork in history after commit
b
. - Branch pointer
b1
points at commitd
,b2
points at commitf
, branchb3
points at commith
.
After. We want the history to look like this:
b1 b2 | | \/ \/ a--b--g--h--c'--d'--e'--f' /\ | b3
That is, we want to cut out commits c--d--e--f
and put them on the top of commit h
.
The backstory. Where all these branches came from? That branch b3
was under public code review while we were independently privately working on functionalities in b1
and after that was done, we were working in the same way on functionalities based on that in branch b2
.
What we want to do. We want to incorporate changes from branch b3
to the code in the second arm of the forked history - the one with branch pointers b1
and b2
. We want to keep the history linear and keep the public history intact (i.e. branch b3
points at the tip of the history tree that is public).
Technical details. In order to do it, execute:
-
git checkout b2
-
git rebase b3
- resolve merge conflicts in all conflicting commits and make sure that the tests run properly
This results in the following commit tree:
b1 b2 | | \/ \/ a--b--c--d \-g--h--c'--d'--e'--f' /\ | b3
Now we need to move branch pointer b1
to commit d'
. This action will also automatically delete the old branch. This is done by executing:
-
git branch -f b1 d'
This results in the desired commit history.
Changing initial history
Before. We have a history like this:
b1 b2 b3 | | | \/ \/ \/ a--b--c--d--e--f--g--h
Where:
- Branch
b1
points at commitd
,b2
points at commitf
, branchb3
points at commith
.
After. We want the history to look like this:
b1 b2 b3 | | | \/ \/ \/ a--i--e'--f'--g'--h'
Where:
- commit
i
is a commit that was created by squashing commitsb
,c
,d
.
The backstory. Where all these branches came from? The branch b1
was under a public code review while branches b2
and b3
were consecutively created based on previous branch. Now we want to squash commits b
, c
, d
from the code review into a single commit before rebasing branch b1
onto master
branch.
What we want to do. We want to change some old history of commits at the beginning of the shown history. To be more precise, we want to squash commits b
, c
, d
.
Technical details. In order to do it, execute:
-
git checkout b3
-
git rebase -i a
- during the interactive rebase session squash commits
b
,c
,d
This results in the following commit tree:
b1 b2 | | \/ \/ a--b--c--d--e--f \-i--e'--f'--g'--h' /\ | b3
The next step is to move branch pointers b1
and b2
to the other arm of the forked history:
-
git branch -f b2 f'
-
git branch -f b1 i'
This results in the desired commit history.
Moving part of the history to another branch
We want to cut off top part of one branch and attach it at the top of another branch. Namely:
before the change we have:
b1 | \/ a--b--c--d--e \-f--g--h--i--j /\ /\ | | b2 b3
while after the change we have:
b1 b3 | | \/ \/ a--b--c--d--e--i'--j' \-f--g--h /\ | b2
In order to do it, execute:
-
git rebase --onto b1 b2 b3
, where:-
b1
is the destination branch pointer (or commit hash) -
b2
is the cut point - the history will be cut after this branch pointer (or commit hash) -
b3
is the tip of the moved history line.
-