git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Jon Seymour <jon.seymour@gmail.com>
Cc: Git Mailing List <git@vger.kernel.org>
Subject: Re: How does git now about future renames during a rebase?
Date: Sun, 6 May 2012 04:52:49 -0400	[thread overview]
Message-ID: <20120506085248.GC27878@sigill.intra.peff.net> (raw)
In-Reply-To: <CAH3Anro6o478A41eXcsFU7guOobQXhqq=DdpNpGWgriRVfqcZQ@mail.gmail.com>

On Sun, May 06, 2012 at 09:41:00AM +0530, Jon Seymour wrote:

> I had a history that looked like this:
> 
> 1. some other commit
> 2. commit that moves files from one directory to a new directory
> 3. commit that edits files in the new directory.
> 
> I then did an interactive rebase to move the commit 3 before commit 2.
> 
> 1. some other commit
> 3a. commit that edits files in the new directory.
> 2a. commit that moves files from one directory to a new directory
> 
> I didn't expect this to work, but somehow git worked out that it
> needed to apply the change in 3 to the original location of the files.
> 
> How does it do this?

When you pick a commit, we actually do a merge between it and the
current HEAD, using the parent of the picked commit as a merge base. So
imagine we have this short history:

  git init repo &&
  cd repo &&
  seq 1 100 >foo && git add foo && git commit -m base &&
  git mv foo bar && git commit -m move &&
  echo 101 >>bar && git add bar && git commit -m change

I.e., a move followed by a change. And you run:

  git rebase -i HEAD~2

and swap the two commits. So afterwards we will have a change followed
by a move. What does git see?

When we pick the first commit ("change"), we end up merging with these
parameters:

  - The "ours" side is "base", with "foo" containing 1..100.
  - The "theirs" side is "change", with "foo" absent and "bar"
    containing 1..101.
  - The ancestor is "move", with "foo" absent and "bar" containing
    1..100.

So rename detection sees that our side moved bar to foo (compared to the
ancestor), and the other side added a line to bar. And it resolves by
putting the modified content into "foo". Now obviously nobody _actually_
moved bar to foo; it was quite the opposite. But that makes sense; a
cherry-pick merge like this sees the reverse of what happened between
the picked commit and the destination commit (less any changes which
have been picked already).

And then we pick the second commit ("move"), with these merge
parameters:

  - The "ours" side is now changed', "foo" containing 1..101.
  - The "theirs" side is "move", with "foo" absent and "bar" containing
    1..100.
  - The ancestor is "base", with "foo" containing 1..100.

Now it looks like their side made a move ("foo" to "bar"), and our
side modified "foo" (i.e., the opposite of the last case). So we again
resolve to put the final content in "bar".

Does that make sense?

-Peff

      reply	other threads:[~2012-05-06  8:53 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-06  4:11 How does git now about future renames during a rebase? Jon Seymour
2012-05-06  8:52 ` Jeff King [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120506085248.GC27878@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=jon.seymour@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).