0

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?

svick
  • 236,525
  • 50
  • 385
  • 514
Franck
  • 560
  • 7
  • 20

2 Answers2

2

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.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • 1
    It is actually much easier: `git update-ref -d $(git symbolic-ref HEAD); git commit -m 'Very bad idea'` – fork0 Sep 12 '12 at 19:55
  • 1
    Thanks; in the meantime I also discovered `git checkout --orphan`, which seems explicitly designed for this kind of thing. – user4815162342 Sep 12 '12 at 20:09
  • `git checkout --orphan new_branch master` is the solution. But the behavior is a little bit strange. Until I do the initial commit, I don't see the new branch. After the initial commit, the new branch is visible and my bash indicates the right current branch. – Franck Sep 13 '12 at 07:53
  • I guess the branch starts off in the same state as `master` immediately following `git init`. Note that the first described method will immediately give you a fully usable branch. – user4815162342 Sep 13 '12 at 09:46
  • Another question about this "--orphan" method. After the orphan branch creation and the initial commit, it looks like Git is unable to fix any conflicts while merging onto this new branch. Is it because the new branch do not have the whole commits history ? – Franck Sep 13 '12 at 12:59
  • Finding a common parent is the prerequisite for merge. This is one of the reasons why this kind of operation is discouraged. – user4815162342 Sep 13 '12 at 13:20
1

As I see you don't understand what a branch is. A branch just a pointer to a commit. When you create a branch from master you don't create any commits, the new branch just points exactly at the same commit as the master, they both represent the same. So, there is nothing to squash or rebase yet, and there is no history yet.

Only after you do some changes and commit them on a branch, then your question will make a sense: how to merge all changes made in a branch as one commit into master? Just use git merge --squash branch.

kan
  • 28,279
  • 7
  • 71
  • 101
  • 1
    He may not know what a git branch is, but it is clear that he doesn't want `git log` to show all the previous commit history, which would happen with normal git branching. In other words, he wants to do something akin to importing the tree of the master branch into a fresh repo created with `git init`. Except he wants to be able to continue working with his other branches and objects in the repo. – user4815162342 Sep 12 '12 at 17:56
  • @user4815162342: frankly, I'm not sure it is what he wants. It is kind of _advanced use_ – fork0 Sep 12 '12 at 19:56
  • It's advanced to you and me, but probably not to the OP. Imagine having a repo with a short linear history of a bunch of test commits. After you're done, you want to squash all of them into a single "initial" commit, from which you will start real work. `git rebase -i` seems perfectly capable of doing the job, except for the minor inconvenience that it cannot start from the very first commit in the history because one cannot give it a theoretical commit-before-the-first to start from! So one feels "stuck" with the silly initial commit, the only alternative being the creation a whole new repo. – user4815162342 Sep 12 '12 at 20:07
  • `git rebase -i` was another solution but so painful and dangerous. I tried an interactive rebase picking the first commit and squashing the others. It was a long job with so many conflicts that I aborted it. – Franck Sep 13 '12 at 07:56