В руководстве по статусу git в разделе «Вывод»> «Краткий формат» подразумевается, что можно переименовать файл только в рабочем дереве.
X Y Meaning
-------------------------------------------------
...
R renamed in work tree
Однако все мои исследования говорят, что git не обнаруживает переименования, пока вы не внесете изменения. Есть ли способ создать этот статус git?
Контекст: я создаю инструмент предварительного просмотра статуса git (https://github.com/PatrickF1/fzf.fish), поэтому мне нужно знать, какие состояния статуса git возможны и как их воспроизвести.
Конечно, это возможно: например, mv foo bar
делает это в любой Unix-подобной системе. Но вот в чем загвоздка: Git обнаружит это как «файл foo
удален, неотслеживаемый файл bar
существует», если нет отслеживаемого файла с именем bar
. И: в случае, когда есть отслеживаемый файл с именем bar
, у вас есть как bar
в индексе (т. е. подготовленный), так и bar
в рабочем дереве (не подготовленный), и они (в настоящее время) считаются «одним и тем же файлом». Таким образом, максимум файл bar
является M
модифицированным.
Все это означает, что в настоящее время статус R
невозможен в столбце Y
. Это зависит от того, как работает обнаружение переименования в Git, что не является официальным свойством Git. Если в будущем код обнаружения переименования изменится, вы увидите статус R
в столбце Y
. Вы просто не можете получить его с версиями Git до 2.38.
Обратите внимание, что удаление файла из индекса приводит только к тому, что файл одновременно удаляется (т. е. «в текущем коммите и отсутствует в индексе») и не отслеживается (т. е. «отсутствует в индексе, присутствует в рабочем дереве»):
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
$ git rm --cached Makefile
$ git status --short
D Makefile
?? Makefile
(а затем git restore -S Makefile
, чтобы исправить это).
Хитрость здесь заключается в том, чтобы помнить следующее:
Индекс содержит каждый файл, который будет в следующем коммите.
Запуск git status
выполняет две внутренние операции git diff --name-status
(ну, за исключением случаев, когда есть неслитые файлы, и в этом случае он делает что-то совершенно другое без предупреждения).
Первый сравнивает HEAD
с index. Результатом сравнения имени и статуса является набор «изменений, подготовленных для фиксации», или первый столбец части XY git status --short
. Здесь возможны следующие варианты: <ничего> (файл не упоминается, потому что ничего не изменилось — это означает, что статус X
будет пустым, если файл должен отображаться в сокращенной форме), M
(файл изменен) , A
или D
(добавлено/удалено), R
если включено обнаружение переименования и есть обнаруженное переименование, C
если включено обнаружение копирования и есть обнаруженная копия, T
если есть изменение статуса (например, файл на символическую ссылку) и так далее на.
Второй git diff --name-status
сравнивает индекс с рабочим деревом. Однако в особом случае все «добавленные» файлы перемещаются в «неотслеживаемый» список, поэтому файлы никогда не добавляются. Если эти файлы также игнорируются, они не будут перечислены, а если нет, то они будут перечислены, но неотслеживаемые файлы могут быть собраны в один «каталог, полный неотслеживаемых файлов», который можно суммировать, например, как path/
.
Как всегда, в настоящее время обнаруживаются переименования (неизвестно заранее). Обнаружение происходит путем наблюдения за тем, что левая и правая стороны операции git diff
удалили файлы слева и добавили файлы справа. Эти пары файлов помещаются в очередь обнаружения переименования. Но поскольку в diff на шаге 4 нет добавленных файлов, переименование не может произойти. Копии также обнаруживаются и имеют аналогичную проблему. Так что в настоящее время ни статус R, ни статус C не могут отображаться здесь.
Некоторые небольшие изменения во внутренних элементах git status
могут изменить это поведение, поэтому, если вы используете git status
программно, вы сможете обработать результат.
(Вот еще один редкий и своеобразный пример текущего необычного вывода:
$ git rm Makefile
$ ln -s foo Makefile
$ git add Makefile
$ git status --short
T Makefile
$ git restore -s HEAD -W Makefile
$ git status --short
TT Makefile
Вы, вероятно, не столкнетесь с этим в дикой природе.)
Контекст: я создаю инструмент предварительного просмотра статуса git... поэтому мне нужно знать, какие состояния статуса git возможны и как их воспроизвести.
Вывод из git status
, даже с --short
, как правило, не подходит для машинного синтаксического анализа. Использование git status --porcelain
, желательно с --porcelain=v2
и -z
, для машинного анализа.