If you have a huge commit history, you may want get to a smaller branch with short history and push it to a new remote for new developers. In this post, we show you how to do that.
The thought is simple, we would create a new base commit that will have no parents and make the commits that we want them in the new branch to rebase onto it, thus we get a branch with less commits and we then push it to remote. Like a shallow clone, if an user clones the repository with less history from that remote and want more history later, it is also possible to do that.
We shall show you how to do that with a full example. The example comes from git book: replace, here we make the process more clearer for you.
Create a short branch and push it to the remote
Assuming we have a repository with below 5 commits and we want a branch named short-history that holding just the 4th and the 5th commit.
$ git log --oneline
* eee5b39 (HEAD -> master) 5th commit
* 0507fc9 4th commit
* d38324c 3rd commit
* 0f302d0 2nd commit
* 0d74a45 1st commit
Step 1. Create new branch to push
# Create and checkout a new branch
$ git checkbout -b short-history
# Now the repo looks like:
$ git log --oneline --decorate
* eee5b39 (HEAD -> master, short-history) 5th commit
* 0507fc9 4th commit
* d38324c 3rd commit
* 0f302d0 2nd commit
* 0d74a45 1st commit
Step 2. Create new base commit for the short branch
In this step, we create a new base commit for the 4th and 5th commit. It is useful to create a base commit that contains information of the old parent d38324c
(the 3rd commit). Therefore we use that commit’s top-level tree to create the base commit (a commit normally contains a top-level tree, the parent commits if any and the committer information).
$ echo 'new base commit with tree from d38324c' | git commit-tree d38324c^{tree}
dab34243e0301c42176e5c8895c0acee1397a1e2
commit-tree
is a low-level git command to create a commit object. Here we pass a tree SHA-1 to it and a commit message to create a commit that will have no parents.
Step 3. Rebase the branch to the new base commit
# Rebase to the new base commit
$ git rebase --onto dab3424 d38324c
Successfully rebased and updated refs/heads/short-history.
# Now the repo looks like:
$ git log --oneline --decorate
* 0b4d7b4 (HEAD -> short-history) 5th commit
* 2172414 4th commit
* dab3424 new base commit with tree from d38324c
* eee5b39 (master) 5th commit
* 0507fc9 4th commit
* d38324c 3rd commit
* 0f302d0 2nd commit
* 0d74a45 1st commit
Now we’ve re-written the short branch that only contains a base commit dab3424
and the 4th and 5th commit as we wanted. The old branch master
remasters as it was.
4. Push the short branch to remote
Now we are ready to push the short branch short-history
to a new remote.
# Push the new branch to a new remote
$ git remote add short-remote <short-remote-url>
$ git push short-remote short-history:master
If we clone from that remote, we will get 3 commits as expected:
$ git clone <short-remote-url>
$ cd <repo-folder>
$ git log --oneline master
0b4d7b4 (HEAD -> short-history) 5th commit
2172414 4th commit
dab3424 new base commit with tree from d38324c
Fetch more history later to the short history
If we want more history later in the repository that we just cloned, we can fetch from a remote with old commit history and use git replace
to combine them. git replace
is a command can be used to replace a commit with another one to rebuild the entire history.
Suppose the remote repository with the old history contains the 1st, 2nd, 3rd and 4th commit (Yes, this is also a way to split a huge repository to two repos that one with the old history and one with the new history). Below is how to do that.
# Add remote that has the old history
$ git remote add long-remote <long-remote-url>
# View the commits in the old history
$ git log --oneline long-remote/master
* 0507fc9 4th commit
* d38324c 3rd commit
* 0f302d0 2nd commit
* 0d74a45 1st commit
# Replace the 4th commit in the short history with the 4th commit in the old history
# to combine them.
$ git replace 2172414 0507fc9
# Now the branch looks like:
$ git log --oneline master
* 0b4d7b4 5th commit
* 2172414 4th commit
* d38324c 3rd commit
* 0f302d0 2nd commit
* 0d74a45 1st commit
Even it shows 2172414
for the 4th commit, it is actually 0507fc9
that we replace it with.