Исходный файл, который был разделен на 2 других файла, есть способ в git, чтобы узнать, что там происходит?

Моя проблема:

Я обозреватель кода, у меня есть ситуация в GIT:

  • before: a.txt

Затем разработчик решил разделить содержимое a.txt на 2 файла и добавить несколько изменений в один коммит:

  • после: b.txt + несколько изменений и c.txt + несколько изменений

Есть ли простой способ увидеть:

  • что получилось от b?
  • что произошло с c?
  • все дополнительные изменения, кроме всего лишь движущихся вещей?

Конкретная команда поможет много.

Также будет помогать определенная политика/рабочий процесс, который предотвращает подобные проблемы (когда нет возможности визуально различать изменения).

UPDATE

Не смущайтесь, увидев награду, поданную ниже, я не санкционировал ее, потому что я не думаю, что это хороший ответ.

Ответ 1

Есть ли простой способ увидеть:

  • что получилось от b?
  • что произошло с c?
  • все дополнительные изменения, кроме всего лишь движущихся вещей?

Я не думаю, что есть какой-либо способ извлечь эту информацию, кроме визуального осмотра diff. Однако похоже, что мы сможем обнаружить разделенные файлы с помощью git diff вместе с аргументом -C. Например, я начинаю с файла, который содержит 38 строк, и перемещает 24 в один файл и 14 в другой (и удаляет оригинал). git diff --name-status просто говорит мне, что я переименовал один файл и добавил другое:

R060    lorem.txt       fileA
A       fileB

Но если мы модифицируем нашу командную строку для обнаружения копий:

git diff --name-status -C30 HEAD^

Получаем:

C060    lorem.txt       fileA
R039    lorem.txt       fileB

Аргумент -C30 говорит: "Рассмотрите файл как копию, если она по крайней мере на 30% похожа на другой файл, включенный в commit". Обратите внимание, что существует соответствующая опция -M, которая контролирует обнаружение переименования; по умолчанию используется 50%.

Некоторая политика/рабочий процесс, который предотвращает подобные проблемы, также поможет.

Что именно вы пытаетесь предотвратить? На самом деле не все равно, чтобы отличить "я разбил файл на два новых файла" из "Я удалил файл и создал два новых файла".

Вы могли бы теоретически предотвратить коммиты, которые вводят новые файлы и изменяют существующие файлы. Например, это было бы относительно легко с помощью крюка pre-receive. Но в такой общей ситуации я не уверен, что вы захотите сделать это на практике.

Для вышесказанного может работать a pre-receive, как показано ниже:

#!/bin/bash                                                                      

while read old new ref; do
        while read type name; do
                if [ "$type" = "A" ]; then
                        has_new=1
                else
                        has_mod=1
                fi
        done < <(git show --name-status --format='' $new)
done

if [ "$has_new" = 1 -a "$has_mod" = 1 ]; then
        echo "ERROR: commits may not both create and modify files" >&2
        exit 1
fi

exit 0

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

#!/bin/bash

while read old new ref; do
    git diff --name-status -C30 $old $new |
        awk '
            {total[$2]++}
            END {for (i in total) if (total[i] > 1) exit 1}
        '

    if [ $? -ne 0 ]; then
        echo "ERROR: detected a split file"
        exit 1
    fi
done

exit 0

Это приведет к выходу с ошибкой, если какой-либо файл будет отображаться как "старое имя" для файла более одного раза. Попытка нажать в хранилище, используя этот крюк pre-receive, используя пример, приведенный в первой части этих ответов, получить меня:

$ git push
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 1.46 KiB | 1.46 MiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
remote: ERROR: detected a split file
To upstream
 ! [remote rejected] master -> master (pre-receive hook declined)

Может быть, это помогает? Без обширного тестирования я бы беспокоился о ложных срабатываниях с этим решением.