4

On git-filter-branch, it is said:

To set a commit (which typically is at the tip of another history) to be the parent of the current initial commit, in order to paste the other history behind the current history:

git filter-branch --parent-filter 'sed "s/^\$/-p <graft-id>/"' HEAD

(if the parent string is empty - which happens when we are dealing with the initial commit - add graftcommit as a parent).

This is exactly what I want to, i.e. to set the parent (to commit A) of some root commit (B). See here for a related question.

But what exactly is the graft-id in that command? Is that the new parent, i.e. A?

Further on, an even simpler example is given to achieve the same:

or even simpler:

echo "$commit-id $graft-id" >> .git/info/grafts
git filter-branch $graft-id..HEAD

Again, what is $graft-id supposed to be in this example? And $commit-id = A, right? Or is it $commit-id = B and $graft-id = A?

I also read this but I still don't really understand why I need such a concept here. Why can't I just do git filter-branch A..HEAD or so?


Ok, I think I figured it all out, see my own answer.

To explain why I needed it:

In our project OpenLieroX, we had Google Breakpad included at one point.

We didn't took it from the official SVN (because it didn't worked at that time for me) but from the latest LastFM stable instead (it was just random that is was from there -- I had it also on my disk and knew that the LastFM people probably took some stable Breakpad version).

Then, when time went on, we applied several patches to our own copy of Google Breakpad.

Now, many months later, we want to clean the histories a bit up, get a good overview of all our patches to Breakpad and maybe also get them upstream. And most importantly (for us), we want to update our copy of Breakpad.

So, I thought that the best thing would be to create a new Git repository, fetch the official source history from somewhere into it and get all the Breakpad specific stuff from our main repository via git filter-branch into it. I used this Breakpad mirror as a base. The filter-branch was also a bit more complicated because we moved the whole Breakpad directory at one point inside the OpenLieroX repository.

So I ended up with three branches:

  • breakpad-in-mainsrc: git filter-branch-first-run for the time when Breakpad was in src/breakpad/external.
  • breakpad-in-libs: git filter-branch-second-run for the time when Breakpad was in libs/breakpad.
  • official: Copy of master from the Breakpad mirror.

Then I searched for the commit in official which was most close to the root in breakpad-in-mainsrc. I didn't got any perfect match, so I used the most close one (wrote a small Python script to figure that out). This one is tagged now as olx-closest-initial-breakpad.

And then I wanted to merge these three histories all together. This went fine the way described above (and given my own answer below).

The result is here: OpenLieroX Google Breakpad on GitHub

Community
  • 1
  • 1
Albert
  • 65,406
  • 61
  • 242
  • 386
  • Are you sure you want to rewrite history? This means that if you'll find a bug related to `breakpad`, and you want to understand when did it emerge - it might be impossible, as the original code you shipped is gone. – Elazar Leibovich Jun 12 '11 at 20:48

2 Answers2

4

Ok, it seems to work the way I expected. To answer my own questions:

  • graft-id is really nothing else than a commit-id, i.e. the SHA1 of a commit.
  • $commit-id = B (it must be a SHA1 though, no tags or so)
  • $graft-id = A (again, must be a SHA1)

Then the given even simpler way works as expected.

Albert
  • 65,406
  • 61
  • 242
  • 386
  • If you are answering this question yourself, it might make sense to share some of your knowledge and explain _what you're doing_. There are a number of caveats with history rewriting and graft points in particular (you cannot undo filtering the branch to make grafts permanent) – sehe May 22 '11 at 15:03
  • 1
    @sehe: I have extended my question now with some background information. – Albert May 22 '11 at 15:18
2

This is a rather obscure feature.

If you should need this, you better make doubly sure you know exactly how git works behind the scenes and you know what it is you wanted to achieve.

Also, there is a newer, probably more useful (at least it is more flexible) feature called git replace (man page)

IMHO that same documentation contains ample info should you really need this.

But see

  1. https://git.wiki.kernel.org/index.php/GraftPoint
  2. What are .git/info/grafts for?
  3. http://bugsquash.blogspot.com/2010/03/stitching-git-histories.html
Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Yea I understand how Git works. It works exactly like expected. See my own answer. I added some explanation why I needed it. – Albert May 22 '11 at 15:01