Использование git diff для обнаружения движения кода + как использовать параметры diff

считайте, что файл (1.c) содержит три функции и изменения, внесенные авторами M и J. Если кто-то запускает git blame 1.c, он получит следующий результат:

^869c699 (M 2012-09-25 14:05:31 -0600  1) 
de24af82 (J 2012-09-25 14:23:52 -0600  2) 
de24af82 (J 2012-09-25 14:23:52 -0600  3) 
de24af82 (J 2012-09-25 14:23:52 -0600  4) public int add(int x, int y)  {
de24af82 (J 2012-09-25 14:23:52 -0600  5)    int z = x+y;
de24af82 (J 2012-09-25 14:23:52 -0600  6)    return z;
de24af82 (J 2012-09-25 14:23:52 -0600  7) }  
de24af82 (J 2012-09-25 14:23:52 -0600  8) 
^869c699 (M 2012-09-25 14:05:31 -0600  9) public int multiplication(int y, int z){
^869c699 (M 2012-09-25 14:05:31 -0600 10)    int result = y*z;
^869c699 (M 2012-09-25 14:05:31 -0600 11)    return temp;
^869c699 (M 2012-09-25 14:05:31 -0600 12) }
^869c699 (M 2012-09-25 14:05:31 -0600 13) 
^869c699 (M 2012-09-25 14:05:31 -0600 14) public void main(){
de24af82 (J 2012-09-25 14:23:52 -0600 15)    //this is a comment
de24af82 (J 2012-09-25 14:23:52 -0600 16) }

теперь, если автор A изменяет позицию multiplication() и add() функции и фиксирует изменения, git blame смогите обнаружить движение кода. См. следующий вывод:

$ git blame  -C -M e4672cf82 1.c
^869c699 (M 2012-09-25 14:05:31 -0600  1) 
de24af82 (J 2012-09-25 14:23:52 -0600  2) 
de24af82 (J 2012-09-25 14:23:52 -0600  3) 
e4672cf8 (M 2012-09-25 14:26:39 -0600  4) 
de24af82 (J 2012-09-25 14:23:52 -0600  5) 
^869c699 (M 2012-09-25 14:05:31 -0600  6) public int multiplication(int y, int z){
^869c699 (M 2012-09-25 14:05:31 -0600  7)    int result = y*z;
^869c699 (M 2012-09-25 14:05:31 -0600  8)    return temp;
^869c699 (M 2012-09-25 14:05:31 -0600  9) }
^869c699 (M 2012-09-25 14:05:31 -0600 10) 
^869c699 (M 2012-09-25 14:05:31 -0600 11) public void main(){
de24af82 (J 2012-09-25 14:23:52 -0600 12)    //this is a comment
e4672cf8 (M 2012-09-25 14:26:39 -0600 13) }
de24af82 (J 2012-09-25 14:23:52 -0600 14) public int add(int x, int y){
de24af82 (J 2012-09-25 14:23:52 -0600 15)    int z = x+y;
de24af82 (J 2012-09-25 14:23:52 -0600 16)    return z;
e4672cf8 (M 2012-09-25 14:26:39 -0600 17) }

однако, если я попытаюсь запустить git diff между этими двумя ревизиями, он не может определить, что функции изменяют их расположение и дает следующий результат:

$ git diff -C -M de24af8..e4672cf82 1.c

diff --git a/1.c b/1.c
index 5b1fcba..56b4430 100644
--- a/1.c
+++ b/1.c
@@ -1,10 +1,7 @@



-public int add(int x, int y){
-       int z = x+y;
-       return z;
-}      
+

public int multiplication(int y, int z){
    int result = y*z;
@@ -13,4 +10,8 @@ public int multiplication(int y, int z){

 public void main(){
    //this is a comment
-}
 No newline at end of file
+}
+public int add(int x, int y){
+       int z = x+y;
+       return z;
+}      
 No newline at end of file

мои вопросы:

  1. как я могу обеспечить обнаружение движения кода при получении вывода diff? Это вообще возможно?

  2. git diff может применяться с несколькими вариантами. Например --minimal, --patience. Как я могу применить эти варианты? Я попытался с одним, но получил следующую ошибку:

    $ git diff --minimal de24af8..e4672cf82 1.c
    usage: git diff <options> <rev>{0,2} -- <path>*
    

может ли кто-нибудь предложить / дать пример примера как правильно добавить эти параметры?

3 ответов


что вы работаете против вот, что Git во многом остается вне расширенный сравниваете такой. Есть причина, по которой Git позволяет настраивать внешние инструменты diff и merge: вы сойдете с ума без их помощи. Вне всякого сравнения и Араксис слияние бы оба поймать это движение, в качестве примера.

общий класс проблемы вы хотите решить-это "структурированное объединение": структурное различие двух исходных файлов java

у вас может быть немного больше удачи с git-format-patch чем с git-diff в этом случае, потому что первый предоставляет больше информации фиксации, включая автора и сообщение фиксации, а также генерирует файл исправления для каждой фиксации в указанном диапазоне. Источник:в чем разница между "git format-patch и "git diff"?

если вы ищете советы по обнаружению кодовых движений в целом, интересно отметить, что обнаружение движения кода явно не цель всемогущего кирка. Смотрите этот интересный обмен:http://gitster.livejournal.com/35628.html

если вы хотите обнаружить, кто поменял заказ, кажется, ваш единственный вариант-сделать что-то вроде:

 git log -S'public int multiplication(int y, int z){
    int result = y*z;
    return temp;
 }

 public void main(){
    //this is a comment
 }
 public int add(int x, int y)  {
    int z = x+y;
    return z;
 }'

то, что вы ищете-это git blame -M<num> -n, который делает что-то очень похожее на то, что ты спрашиваешь:

-M|<num>|
       Detect moved or copied lines within a file. When a commit moves or
       copies a block of lines (e.g. the original file has A and then B,
       and the commit changes it to B and then A), the traditional blame
       algorithm notices only half of the movement and typically blames
       the lines that were moved up (i.e. B) to the parent and assigns
       blame to the lines that were moved down (i.e. A) to the child
       commit. With this option, both groups of lines are blamed on the
       parent by running extra passes of inspection.

       <num> is optional but it is the lower bound on the number of
       alphanumeric characters that git must detect as moving/copying
       within a file for it to associate those lines with the parent
       commit. The default value is 20.

-n, --show-number
       Show the line number in the original commit (Default: off).

по состоянию на Git 2.15,git diff теперь поддерживает обнаружение перемещенных линий с помощью . Он даже обнаруживает перемещения между файлами.

это работает, очевидно, для цветного вывода. Насколько я могу судить, нет возможности указывать перемещения в формате текстового патча, но это имеет смысл.

для поведения по умолчанию, попробуйте

git diff --color-moved

команда также принимает параметры, которые в настоящее время являются no, default, plain, zebra и dimmed_zebra (использовать git help diff чтобы получить последние варианты и их описания). Например:

git diff --color-moved=zebra

в данном конкретном случае, я не думаю, что git diff беспокоится об обнаружении движения кода; скорее, это просто создание патча, который может быть применен для преобразования старого файла в новый файл, который является вашим git diff вывод ясно показывает - функция удаляется из одного места и вставляются в другое. Вероятно, есть более краткие способы вывода серии команд редактирования, которые перемещают код из одного места в другое, но я думаю git может быть ошибочным на стороне переносимость здесь - нет никакой гарантии, что конечная пользовательская рана всегда использует git apply или git am, поэтому патч создается в формате, который может использоваться даже с plain patch.