Как сравнить рабочее дерево с фиксацией?
Я использую
git diff mycommit
для сравнения моего рабочего дерева с mycommit
, но он, кажется, игнорирует файлы, отсутствующие в текущем индексе. Вы можете воспроизвести его следующим образом:
git init
echo A > A.txt; git add .; git commit -m A; git branch A
echo B > B.txt; git add .; git commit -m B; git branch B
git reset --hard A
echo BB > B.txt
git diff B
Выход (с git версия 1.7.3.3) пуст. Использование --diff-filter=ACDMRTUXB
показывает "удаленный файл", что также неверно, так как файл B.txt
существует как в рабочем дереве, так и в commit B
. IMHO, файл должен быть указан как измененный. Удивительно, но он работает после добавления файла в индекс, хотя это не индекс, который сравнивается. Как я могу получить правильный diff без него?
Ответы
Ответ 1
manojlds написал в своем ответе
В принципе, diff не учитывает файлы без следа. Вот почему вы видите, что файл удален, поскольку diff совпадает с git diff B A
Это верно и стоит того, чтобы оправдать меня, но это меня не удовлетворило, поскольку он говорит, что ни "как я могу его сравнить" не дал ему более глубокой причины. Я все еще думал, что это ошибка, поэтому я спросил на форуме git и получил длинный ответ тем, кто точно знает. Для меня важны следующие детали:
Определение путей в рабочем дереве в этих предложениях - это не "все файлы в файловой системе", либо "все файлы в файловой системе, отфильтрованные с помощью механизма игнорирования". Это "все файлы в файловой системе, которые находятся в индексе"...
и
..., который даст чистую семантику "git diff HEAD": какое изменение я буду записывать, если я сказал "git commit -a" в этот момент?
Ответ 2
Простая графика может помочь:
![enter image description here]()
Итак, вы можете запросить три типа различий:
-
git diff --cached
В этом разница между тем, что находится в индексе и последней фиксацией. Он показывает вам, что изменения будут в следующем фиксации.
-
git diff
Это показывает разницу между индексом и рабочим деревом. Это изменения, внесенные вами в файлы с момента последнего добавления их в индекс. Вот почему я не получал никаких результатов. У меня не было никаких изменений между индексом и рабочим деревом.
-
git diff HEAD
Это показывает разницу между файлами в рабочем дереве и последним фиксацией. Здесь есть информация: если вы внесли изменения, добавили их в индекс, а затем отменили эти изменения в рабочем дереве, вы не получите никаких результатов для git diff HEAD
(потому что нет никакой разницы), но вы получите результат для git diff --cached
, поскольку в индексе все еще есть изменения.
И если вы хотите сравнить его с предыдущими коммитами:
![enter image description here]()
Это просто сравнивается с предыдущими коммитами, но вы можете заменить HEAD~
на любую другую ссылку на фиксацию.
Ответ 3
Вопрос в том, что я добавил файл в свое рабочее дерево, существующее в другом коммите. Почему git diff <commit>
не показывает разницу между содержимым файла, которое существует в моем рабочем дереве, и содержимым файла, находящегося в другом коммите.
Это связано с тем, что новый файл, который вы добавили, не отслеживается, и, следовательно, git не отслеживает его.
Попробуйте git diff HEAD
, вы не увидите, что вы добавили B.txt в свое рабочее дерево.
В принципе, diff не учитывает файлы без следа. Вот почему вы видите, что файл удален, потому что diff совпадает с git diff B A
Теперь, если вы должны добавить файл, вы увидите ожидаемый результат, потому что git отслеживает его сейчас.
Скажем, вы передали файл, а затем изменили содержимое в рабочем дереве:
Теперь git diff HEAD
покажет разницу между рабочим деревом и HEAD, показывая изменение, которое вы сделали в своем рабочем дереве в отслеживаемых файлах. То же самое с git diff B
Ответ 4
Если все, что вам нужно, это вернуть изменения в рабочем дереве в ветку/коммит B, вы можете сделать:
git diff B | git apply -R
Это создаст разницу между B и рабочим деревом и применит его в обратном порядке.