# rewrite history

9 messages from 2011-06-16 to 2011-06-16. Participants: Ilya Basin, Jeff King, Junio C Hamano, Marc Branchaud.
Thread: https://gitlist.dev/t/27638

## Ilya Basin, 2011-06-16 19:17

Subject: rewrite history
Message-ID: <362053118.20110616231758@gmail.com>
URL: https://gitlist.dev/e/362053118.20110616231758%40gmail.com

```
Hi list. There were 2 branches. One's HEAD was modified to match a
specific commit at another branch. Now, how to merge them according to
this scheme?

A---B---X---E---F
                     =>  C---D---X---E---F
C---D---X'

X and X' have no difference. I tried to write a script to cherry-pick
E and F, but some of commits are merges and cherry-pick fails.

```

## Jeff King, 2011-06-16 19:26

Subject: Re: rewrite history
Message-ID: <20110616192644.GB13466@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20110616192644.GB13466%40sigill.intra.peff.net
In-Reply-To: <362053118.20110616231758@gmail.com>

```
On Thu, Jun 16, 2011 at 11:17:58PM +0400, Ilya Basin wrote:

> Hi list. There were 2 branches. One's HEAD was modified to match a
> specific commit at another branch. Now, how to merge them according to
> this scheme?
> 
> A---B---X---E---F
>                      =>  C---D---X---E---F
> C---D---X'
> 
> X and X' have no difference. I tried to write a script to cherry-pick
> E and F, but some of commits are merges and cherry-pick fails.

I think you just want to rebase using the "-p" option to preserve
merges. Something like:

  $ git checkout -b rebased-branch F
  $ git rebase -p --onto D B

that will pick X, E, and F, and replay them on top of D, resulting in
the graph you showed above. You could also do:

  $ git rebase -p --onto X' X

if you wanted to keep X' instead of X.

The new history will be stored on "rebased-branch". You can make sure it
looks good to you, and then:

  $ git branch -f my_original_branch rebased-branch

to move the state over to your original branch. You could also just do
the rebase directly on the original A-B-X-E-F branch.

-Peff

```

## Junio C Hamano, 2011-06-16 19:43

Subject: Re: rewrite history
Message-ID: <7vhb7ph8aj.fsf@alter.siamese.dyndns.org>
URL: https://gitlist.dev/e/7vhb7ph8aj.fsf%40alter.siamese.dyndns.org
In-Reply-To: <20110616192644.GB13466@sigill.intra.peff.net>

```
Jeff King <peff@peff.net> writes:

> On Thu, Jun 16, 2011 at 11:17:58PM +0400, Ilya Basin wrote:
>
>> Hi list. There were 2 branches. One's HEAD was modified to match a
>> specific commit at another branch. Now, how to merge them according to
>> this scheme?
>> 
>> A---B---X---E---F
>>                      =>  C---D---X---E---F
>> C---D---X'
>> 
>> X and X' have no difference. I tried to write a script to cherry-pick
>> E and F, but some of commits are merges and cherry-pick fails.
>
> I think you just want to rebase using the "-p" option to preserve
> merges. Something like:
>
>   $ git checkout -b rebased-branch F
>   $ git rebase -p --onto D B
>
> that will pick X, E, and F, and replay them on top of D, resulting in
> the graph you showed above.

Eh, careful. Nobody said the change between B and X is any similar to the
change between D and X'. Replaying the changes E and F introduce on top of
X' to arrive at C--D--X'-E--F is the best you could do, i.e.

>   $ git rebase -p --onto X' X
>
> if you wanted to keep X' instead of X.

is more like "even if you wanted to keep X instead of X'".

If you prefer commit message of X over X', you can rebase -i it after you
are done the first round to get rid of A and B, though.

But wouldn't filter-branch a better tool for this?  Graft to pretend that
the parent of X is D instead of B, and filter the branch with F at its
tip, that is.

```

## Jeff King, 2011-06-16 19:49

Subject: Re: rewrite history
Message-ID: <20110616194911.GA14355@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20110616194911.GA14355%40sigill.intra.peff.net
In-Reply-To: <7vhb7ph8aj.fsf@alter.siamese.dyndns.org>

```
On Thu, Jun 16, 2011 at 12:43:00PM -0700, Junio C Hamano wrote:

> >> Hi list. There were 2 branches. One's HEAD was modified to match a
> >> specific commit at another branch. Now, how to merge them according to
> >> this scheme?
> >> 
> >> A---B---X---E---F
> >>                      =>  C---D---X---E---F
> >> C---D---X'
> >> 
> >> X and X' have no difference. I tried to write a script to cherry-pick
> >> E and F, but some of commits are merges and cherry-pick fails.
> >
> > I think you just want to rebase using the "-p" option to preserve
> > merges. Something like:
> >
> >   $ git checkout -b rebased-branch F
> >   $ git rebase -p --onto D B
> >
> > that will pick X, E, and F, and replay them on top of D, resulting in
> > the graph you showed above.
> 
> Eh, careful. Nobody said the change between B and X is any similar to the
> change between D and X'. Replaying the changes E and F introduce on top of
> X' to arrive at C--D--X'-E--F is the best you could do, i.e.

I thought that was exactly what Ilya said with "X and X' have no
difference". I assumed that meant "they are semantically similar commits
on different bases" (i.e., a cherry-pick) and not "they have the exact
same tree state" (i.e., "git diff X X'" is empty).

> But wouldn't filter-branch a better tool for this?  Graft to pretend that
> the parent of X is D instead of B, and filter the branch with F at its
> tip, that is.

If my assumption on the meanings is reversed (i.e., X and X' really are
the same tree state, not introducing equivalent commits), then yeah,
that would be better.

-Peff

```

## Ilya Basin, 2011-06-16 20:06

Subject: Re[2]: rewrite history
Message-ID: <17721660.20110617000644@gmail.com>
URL: https://gitlist.dev/e/17721660.20110617000644%40gmail.com
In-Reply-To: <20110616194911.GA14355@sigill.intra.peff.net>

```
JK> On Thu, Jun 16, 2011 at 12:43:00PM -0700, Junio C Hamano wrote:

>> >> Hi list. There were 2 branches. One's HEAD was modified to match a
>> >> specific commit at another branch. Now, how to merge them according to
>> >> this scheme?
>> >> 
>> >> A---B---X---E---F
>> >>                      =>  C---D---X---E---F
>> >> C---D---X'
>> >> 
>> >> X and X' have no difference. I tried to write a script to cherry-pick
>> >> E and F, but some of commits are merges and cherry-pick fails.
>> >
>> > I think you just want to rebase using the "-p" option to preserve
>> > merges. Something like:
>> >
>> >   $ git checkout -b rebased-branch F
>> >   $ git rebase -p --onto D B
>> >
>> > that will pick X, E, and F, and replay them on top of D, resulting in
>> > the graph you showed above.
>> 
>> Eh, careful. Nobody said the change between B and X is any similar to the
>> change between D and X'. Replaying the changes E and F introduce on top of
>> X' to arrive at C--D--X'-E--F is the best you could do, i.e.

JK> I thought that was exactly what Ilya said with "X and X' have no
JK> difference". I assumed that meant "they are semantically similar commits
JK> on different bases" (i.e., a cherry-pick) and not "they have the exact
JK> same tree state" (i.e., "git diff X X'" is empty).

>> But wouldn't filter-branch a better tool for this?  Graft to pretend that
>> the parent of X is D instead of B, and filter the branch with F at its
>> tip, that is.

JK> If my assumption on the meanings is reversed (i.e., X and X' really are
JK> the same tree state, not introducing equivalent commits), then yeah,
JK> that would be better.

JK> -Peff

sorry,
git diff X X' is empty


-- 

```

## Jeff King, 2011-06-16 20:13

Subject: Re: rewrite history
Message-ID: <20110616201300.GA14674@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20110616201300.GA14674%40sigill.intra.peff.net
In-Reply-To: <17721660.20110617000644@gmail.com>

```
On Fri, Jun 17, 2011 at 12:06:44AM +0400, Ilya Basin wrote:

> JK> I thought that was exactly what Ilya said with "X and X' have no
> JK> difference". I assumed that meant "they are semantically similar commits
> JK> on different bases" (i.e., a cherry-pick) and not "they have the exact
> JK> same tree state" (i.e., "git diff X X'" is empty).
> [...]
> sorry,
> git diff X X' is empty

Oh, then ignore everything I said. :)

I think you want to graft and filter-branch as Junio mentioned.

-Peff

```

## Marc Branchaud, 2011-06-16 21:33

Subject: Re: rewrite history
Message-ID: <4DFA76B6.5030407@xiplink.com>
URL: https://gitlist.dev/e/4DFA76B6.5030407%40xiplink.com
In-Reply-To: <362053118.20110616231758@gmail.com>

```
On 11-06-16 03:17 PM, Ilya Basin wrote:
> Hi list. There were 2 branches. One's HEAD was modified to match a
> specific commit at another branch. Now, how to merge them according to
> this scheme?
> 
> A---B---X---E---F
>                      =>  C---D---X---E---F
> C---D---X'
> 
> X and X' have no difference. I tried to write a script to cherry-pick
> E and F, but some of commits are merges and cherry-pick fails.
> 
> ...
> 
> git diff X X' is empty

It sounds like you really want to apply X--E--F on top of D, but I don't know
how you can do that since you need to do *something* to D in order to get a
tree that matches X, and that something is (presumably) *different* from the
change that X applied to B.  So if

	diff B X  !=  diff D X'

then I think Junio's right that the best you can do is change the meta-data
in X' (commit message, Author, etc) to match X then apply E and F on top of
that.  But filter-branch seems like overkill to me here -- I'd just use
"rebase -p" but not quite as Peff described:

	git checkout X'
	git commit --amend ....   # Replaces X' with X"
	git rebase -p --onto HEAD X F

Giving you

	C---D---X"---E---F

where

	diff D X'  ==   diff D X"
and	meta_data(X") == meta_data(X)

But if you're happy with C---D---X'---E---F then you can skip the "git commit
--amend" step.

		M.

```

## Ilya Basin, 2011-06-16 21:55

Subject: Re[2]: rewrite history
Message-ID: <7310048292.20110617015509@gmail.com>
URL: https://gitlist.dev/e/7310048292.20110617015509%40gmail.com
In-Reply-To: <20110616201300.GA14674@sigill.intra.peff.net>

```
>> sorry,
>> git diff X X' is empty

JK> Oh, then ignore everything I said. :)

JK> I think you want to graft and filter-branch as Junio mentioned.

JK> -Peff

I'm puzzled. How to undo an unfortunate attempt of filter-branch?
git log origin/master returns irrelevant info, although I didn't push
it to origin and I also tried git branch -D master, -rD master and git
fetch -f


-- 

```

## Ilya Basin, 2011-06-16 22:18

Subject: Re[3]: rewrite history
Message-ID: <724671388.20110617021841@gmail.com>
URL: https://gitlist.dev/e/724671388.20110617021841%40gmail.com
In-Reply-To: <7310048292.20110617015509@gmail.com>

```
>>> sorry,
>>> git diff X X' is empty

JK>> Oh, then ignore everything I said. :)

JK>> I think you want to graft and filter-branch as Junio mentioned.

JK>> -Peff

IB> I'm puzzled. How to undo an unfortunate attempt of filter-branch?
IB> git log origin/master returns irrelevant info, although I didn't push
IB> it to origin and I also tried git branch -D master, -rD master and git
IB> fetch -f
Nevermind, forgot to rm .git/info/grafts


-- 

```
