Search code examples
gitrebasesquash

Squashing or rebasing while branching


I'm starting a new branch from my master branch. But I do not want the whole history on the new branch. I would like only 1 commit to start the branch.

I have created the new branch and tried to rebase all the commits but it does not work since I don't have a previous commit. I don't understand that stuff "previous commit"...

Maybe it would be better squashing the commits. But my new branch is already merged with the master when created.

I don't know how to do that. Do you have an idea?


Solution

  • You can do that using a little plumbing:

    tree=$(git log -1 --format=%T master)
    commit=$(git commit-tree $tree -m "initial commit")
    git checkout -b new_branch $commit
    

    Explanation:

    1. Extract only the tree (data) from the current commit on master, because that's what you're really interested in. The SHA1 of the tree object is printed by git log -1 --format=%T, and saved to $tree

    2. Create a commit out of that tree that has no parents. This is done with the plumbing command git commit-tree, which takes a tree object and a commit message, and creates a commit object. It normally also takes the parent commit(s), but in this case we don't want a parent, so we don't give one. The command outputs the SHA1 of the resulting commit, which we save to $commit.

    3. The third, easiest step, is to create a branch with the new commit as a starting point, done with the usual git checkout -b.

    EDIT: A much simpler way to do this is using git checkout --orphan new_branch master followed by git commit -m "Initial commit", with exactly the same results. I'm leaving the above explanation for educational purposes because researching it taught me a few details about git. Also, do note that git makes this hard to do for a reason - history tracing is highly encouraged - so if you're doing this, be sure to have a good reason.