Thread (1 message) 1 message, 1 author, 2016-06-15
  • (off-list ancestor, not in this archive)
  • Re: Rename handling · Junio C Hamano <hidden> · 2016-06-15

Re: Rename handling

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:43:00

"Martin Langhoff" [off-list ref] writes:
In that area, git's mergers still have a bit to go -- I do hope for a
day when I can say git-merge -s refactor or just git-merge -s
tryharder so that it if hunks don't apply, git will try and trace
where the block of code the hunk applies to has gone.
Let's say Oliver creates this project with a single file,
frotz.c.

-- >8 -- Oliver:frotz.c -- >8 --
 1 struct frotz {
 2     int nitfol;
 3     int xyzzy;
 4 };
 5
 6 int add_frotz(struct frotz *it)
 7 {
 8     return it->nitfol + it->xyzzy;
 9 }
-- 8< -- Oliver:frotz.c -- 8< --

Then Alice and Bob forks this project, and makes their own
modification.

Alice does this:

-- >8 -- Alice:frotz.c -- >8 --
 1 struct frotz {
 2     int filfre;
 3     int nitfol;
 4     int xyzzy;
 5 };
 6
 7 int add_frotz(struct frotz *it)
 8 {
 9     return it->filfre + it->nitfol + it->xyzzy;
10 }
-- 8< -- Alice:frotz.c -- 8< --

while Bob does this:

-- >8 -- Bob:frotz.h -- >8 --
 1 #ifndef FROTZ_H
 2 #define FROTZ_H
 3
 4 struct frotz {
 5     int nitfol;
 6     int xyzzy;
 7 };
 8 #endif /* FROTZ_H */
-- 8< -- Bob:frotz.h -- 8< --
-- >8 -- Bob:frotz.c -- >8 --
 1 #include <frotz.h>
 2
 3 int add_frotz(struct frotz *it)
 4 {
 5     return it->nitfol + it->xyzzy;
 6 }
-- 8< -- Bob:frotz.c -- 8< --

Now, Alice wants to merge the results of their efforts.

The "perfect merge strategy" (git-merge-blame) should be able to
detect the situation and ask Alice:

	On Bob's branch, the original file "frotz.c" was split
	into "frotz.h" and "frotz.c", while on your branch, the
	file was not split.  Both branches changed the file(s).

	Do you want to take the split [Y/n]?

We can do this by blaming from Alice:frotz.c, Bob:frotz.c and
Bob:frotz.h down to Oliver (which is the common ancestor
commit).

Let's say Alice likes the split and said yes.  Then, from the
"git-blame -C Bob -- frotz.h" output, git-merge-blame should be
able to figure out that this is what happened:

    B:1 +#ifndef FROTZ_H
    B:2 +#define FROTZ_H
    B:3 +
O:1 B:4  struct frotz {
O:2 B:5     int nitfol;
O:3 B:6     int xyzzy;
O:4 B:7  };
    B:8 +#endif /* FROTZ_H */

Similarly for "git-blame -C Bob -- frotz.c":

    B:1 +#include <frotz.h>
O:5 B:2  
O:6 B:3  int add_frotz(struct frotz *it)
O:7 B:4  {
O:8 B:5      return it->nitfol + it->xyzzy;
O:9 B:6  }

and for "git-blame -C Alice -- frotz.c",

O:1 A:1  struct frotz {
    A:2 +    int filfre;
O:2 A:3      int nitfol;
O:3 A:4      int xyzzy;
O:4 A:5  };
O:5 A:6 
O:6 A:7  int add_frotz(struct frotz *it)
O:7 A:8  {
O:8     -    return it->nitfol + it->xyzzy;
    A:9 +    return it->filfre + it->nitfol + it->xyzzy;
O:9 A:10 }

Looking at this, and because Alice chose to take the file split
Bob made, the merge strategy can insert line A:2 between B:4 and
B:5 to add filfre member to "struct frotz", and update B:5 with
A:9.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help