git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* retrospective move
@ 2009-02-04  8:43 jemmyw
  2009-02-04  9:17 ` Thomas Rast
  0 siblings, 1 reply; 5+ messages in thread
From: jemmyw @ 2009-02-04  8:43 UTC (permalink / raw)
  To: git


Hi. Awhile ago I copied some files in my local repo then commited. In another
commit I deleted the original files, so essentially I did a mv that git
doesn't know about. Now I'm trying to merge from another branch where
changes have happened to the files in their original locations, and it's
making the merge somewhat difficult. Is there a way to ease this?
-- 
View this message in context: http://www.nabble.com/retrospective-move-tp21826423p21826423.html
Sent from the git mailing list archive at Nabble.com.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: retrospective move
  2009-02-04  8:43 retrospective move jemmyw
@ 2009-02-04  9:17 ` Thomas Rast
  2009-02-04 10:31   ` Santi Béjar
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Rast @ 2009-02-04  9:17 UTC (permalink / raw)
  To: jemmyw; +Cc: git

[-- Attachment #1: Type: text/plain, Size: 2439 bytes --]

jemmyw wrote:
> 
> Hi. Awhile ago I copied some files in my local repo then commited. In another
> commit I deleted the original files, so essentially I did a mv that git
> doesn't know about. Now I'm trying to merge from another branch where
> changes have happened to the files in their original locations, and it's
> making the merge somewhat difficult. Is there a way to ease this?

Git never "knows" about a move, it only detects them after the fact.
A corollary of this is that 'git mv a b' is more or less the same as
'cp a b; git rm a; git add b'.

Now since you have a copy followed by a removal in two separate
commits, the merge logic won't treat this as a rename.  Some ideas for
possible solutions:

* If your cp&rm commits are strictly local, you could squash them into
  a single commit.  See man git-rebase(1), especially the -i flag.
  That way, the merge logic will recognise it as a rename.

* You can use an extra line of history that has a "real" one-step mv.
  Suppose you currently have

     *---*---*---*---*      upstream
      \
       \
        +--C--o--R--o--o    local

  where C is the copy and R is the removal.  Then you can introduce an
  extra "gateway" branch that does just the move:

     *---*---*---*---*      upstream
     |\
     | \
     |  +--M                gateway
     |
      \
       \
        +--C--o--R--o--o    local

  Now merge gateway to local (i.e. git checkout local && git merge
  gateway), and resolve all resulting conflicts.  I think you can
  actually use '-s ours' in that merge, but be sure to check the
  results.

     *---*---*---*---*      upstream
     |\
     | \
     |  +--M                gateway
     |      \
      \      +----------+
       \                 \
        +--C--o--R--o--o--1    local

  Finally, you can use the gateway branch to "do the rename" on all
  incoming new changes, by first merging upstream to gateway and later
  again gateway to local, like so:
  
     *---*---*---*---*.      upstream
     |\                \
     | \                \
     |  +--M-------------2       gateway
     |      \             \
      \      +----------+  \
       \                 \  \
        +--C--o--R--o--o--1--3   local

  It won't be very pretty history, but it should only give (rename
  related) merge conflicts at M.

HTH :-)

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: retrospective move
  2009-02-04  9:17 ` Thomas Rast
@ 2009-02-04 10:31   ` Santi Béjar
  2009-02-04 12:33     ` Thomas Rast
  0 siblings, 1 reply; 5+ messages in thread
From: Santi Béjar @ 2009-02-04 10:31 UTC (permalink / raw)
  To: Thomas Rast; +Cc: jemmyw, git

2009/2/4 Thomas Rast <trast@student.ethz.ch>:
> jemmyw wrote:
>>
>> Hi. Awhile ago I copied some files in my local repo then commited. In another
>> commit I deleted the original files, so essentially I did a mv that git
>> doesn't know about. Now I'm trying to merge from another branch where
>> changes have happened to the files in their original locations, and it's
>> making the merge somewhat difficult. Is there a way to ease this?
>
> Git never "knows" about a move, it only detects them after the fact.
> A corollary of this is that 'git mv a b' is more or less the same as
> 'cp a b; git rm a; git add b'.
>
> Now since you have a copy followed by a removal in two separate
> commits, the merge logic won't treat this as a rename.

I don't think it holds. Git only sees the endpoints and the bases, it
does not matter if the "move" was actually two commits. Maybe they
have changed dramatically and git is not able to detect the rename (or
the files are small). Another possible cause could be that you have a
lot of renames (see config merge.renamelimit).

You could see if git detects the rename diffing differents commits:

$ git diff --raw -M commit1 commit2

if it does not detect you could use other limits as:

$ git diff --raw -M50 commit1 commit2

while commit1 and 2 are the endpoints or the merge base.

It could hep if you could provide a minimal test case, or at least the
commands and output you get.

HTH,
Santi

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: retrospective move
  2009-02-04 10:31   ` Santi Béjar
@ 2009-02-04 12:33     ` Thomas Rast
  2009-02-04 12:57       ` Santi Béjar
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Rast @ 2009-02-04 12:33 UTC (permalink / raw)
  To: Santi Béjar; +Cc: jemmyw, git

[-- Attachment #1: Type: text/plain, Size: 1910 bytes --]

Santi Béjar wrote:
> 2009/2/4 Thomas Rast <trast@student.ethz.ch>:
> > jemmyw wrote:
> >>
> >> Hi. Awhile ago I copied some files in my local repo then commited. In another
> >> commit I deleted the original files, so essentially I did a mv that git
> >> doesn't know about. Now I'm trying to merge from another branch where
> >> changes have happened to the files in their original locations, and it's
> >> making the merge somewhat difficult. Is there a way to ease this?
> >
> > Git never "knows" about a move, it only detects them after the fact.
> > A corollary of this is that 'git mv a b' is more or less the same as
> > 'cp a b; git rm a; git add b'.
> >
> > Now since you have a copy followed by a removal in two separate
> > commits, the merge logic won't treat this as a rename.
> 
> I don't think it holds. Git only sees the endpoints and the bases, it
> does not matter if the "move" was actually two commits. Maybe they
> have changed dramatically and git is not able to detect the rename (or
> the files are small). Another possible cause could be that you have a
> lot of renames (see config merge.renamelimit).

Hmm, you're right.  I stand corrected.

Here's a sequence of commands that makes a test case:

  git init
  seq 1 10 > A
  git add A
  git commit -m initial
  seq 11 15 >> A
  git commit -m second A
  seq 16 20 >> A
  git commit -m third
  git checkout -b side HEAD~2
  cp A B
  git add B
  git commit -m copy
  seq 3 10 > B               # <--
  git commit -m edit B
  git rm A
  git commit -m delete

Then running

  git merge master

goes through cleanly, but changing the line indicated above to 'seq 5
10' makes it less similar, falling through the detection and causing a
conflict.  The minimum required similarity for merges does not seem to
be configurable unfortunately.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: retrospective move
  2009-02-04 12:33     ` Thomas Rast
@ 2009-02-04 12:57       ` Santi Béjar
  0 siblings, 0 replies; 5+ messages in thread
From: Santi Béjar @ 2009-02-04 12:57 UTC (permalink / raw)
  To: Thomas Rast; +Cc: jemmyw, git

2009/2/4 Thomas Rast <trast@student.ethz.ch>:

[...]

>
> Here's a sequence of commands that makes a test case:
>
>  git init
>  seq 1 10 > A
>  git add A
>  git commit -m initial
>  seq 11 15 >> A
>  git commit -m second A
>  seq 16 20 >> A
>  git commit -m third
>  git checkout -b side HEAD~2
>  cp A B
>  git add B
>  git commit -m copy
>  seq 3 10 > B               # <--
>  git commit -m edit B
>  git rm A
>  git commit -m delete
>
> Then running
>
>  git merge master
>
> goes through cleanly, but changing the line indicated above to 'seq 5
> 10' makes it less similar, falling through the detection and causing a
> conflict.

Thanks, but that's known, this is why I wrote "or the files are
small". I was not clear, but what I wanted was a *real* test case. In
which cases this is a problem in practice.

>  The minimum required similarity for merges does not seem to
> be configurable unfortunately.

No, but nevertheless it works fine most of the time, except with small files.

HTH,
Santi

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-02-04 13:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-04  8:43 retrospective move jemmyw
2009-02-04  9:17 ` Thomas Rast
2009-02-04 10:31   ` Santi Béjar
2009-02-04 12:33     ` Thomas Rast
2009-02-04 12:57       ` Santi Béjar

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).