Подтвердить что ты не робот

Использование 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

Мои вопросы:

  • Как я могу обеспечить принудительное обнаружение движения кода при получении diff-вывода? Возможно ли это?

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

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

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

4b9b3361

Ответ 1

То, против чего вы столкнулись, состоит в том, что Git в значительной степени остается вне передовых подобных. Там причина Git позволяет конфигурировать внешние инструменты для разграничения и слияния: вы сходите с ума без их помощи. Beyond Compare и Araxis 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).

Ответ 2

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

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

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

git diff --color-moved

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

git diff --color-moved=zebra

Ответ 3

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