Вы делаете одну фундаментальную ошибку, а затем распространяете эту ошибку на каждую из своих различных команд.
Ошибка в том, что вы думаете о фиксации как изменении . Коммит - это не набор изменений. Коммит содержит снимок файлов. Более того, промежуточная область никогда не бывает пустой , 1 , она просто соответствует текущей фиксации , изначально.
Файлы file1.txt
, file2.txt
и file3.txt
существуют в:
- вашем рабочем дереве в виде простых файлов;
- индексной / промежуточной области, как файлы в специальном Git формат фиксации, готовый к фиксации; и
- каждая фиксация.
Каждая копия каждого файла может соответствовать другой копии того же файла (или любого другого файла) или может отличаться .
Имя HEAD
выбирает одну конкретную фиксацию. 2 В начале ваших различных тестов имя HEAD
selected commit ce6f5bb
. Таким образом, на данный момент вам доступны три файла с именами file1.txt
и Git, помимо тех, что указаны в предыдущих коммитах:
ce6f5bb:file1.txt
, иначе HEAD:file1.txt
: эта копия file1.txt
заморожен в фиксации и не может быть изменен. :file1.txt
: эта копия file1.txt
находится в области индекса / промежуточной обработки. Вы можете заменить его новой копией в любое время. file1.txt
: это просто обычный файл. На самом деле это не в Git. Это обычный файл в вашем рабочем дереве.
Также есть три копии file2.txt
и три копии file3.txt
.
Выполняется git diff
без arguments сравнивает все три файла в HEAD
со всеми тремя файлами в вашем рабочем дереве. В выводе упоминаются только те, которые отличаются.
Running git diff --staged
или git diff --cached
сравнивает все три файла в HEAD
со всеми тремя файлами в промежуточной области. В выводе упоминаются только те, которые отличаются.
Запуск git diff HEAD
сравнивает все три файла в HEAD
со всеми тремя файлами в вашем рабочем дереве. В выводе упоминаются только те, которые отличаются.
Обратите внимание, что когда вы используете git log -p
или git show
для просмотра фиксации, Git делает git diff
снимка родительской фиксации - ее файлов - против снимка этого коммита. Вы видите только те файлы, которые отличаются друг от друга. Так что выглядит как фиксация сохраняет изменения, но на самом деле он просто сохраняет снимок.
Обратите внимание, что git status
запускает два git diff
s: один сравнивает HEAD
vs staging-area, т. е. делает git diff --staged
и упоминает только имена файлов без отображения различий. Это изменения, подготовленные для файлов фиксации. Второй diff сравнивает индекс с рабочим деревом, т. Е. Делает git diff
и упоминает только имена файлов. Это изменения, не поставленные для фиксации .
1 Промежуточная область может быть полностью пустой и находится в свободном sh репозиторий, в котором еще нет файлов и еще нет git add
-ed. Вы также можете git rm
каждый файл, в результате чего промежуточная область станет пустой. Но обычно он полон копий файлов из коммита HEAD
, пока вы не используете git add
для замены этих файлов на файлы из рабочего дерева.
2 Вы можете задайте Git два вопроса о специальном имени HEAD
:
git rev-parse HEAD
спрашивает Git Что ha sh ID представляет HEAD
, т.е. каков текущий коммит? Это тот, который спрашивает git diff
. Или:
git symbolic-ref HEAD
git rev-parse --symbolic-full-name HEAD
спрашивает Git Какое имя ветки обозначает HEAD
, т.е. какая ветка git status
сообщит, что я нахожусь? Этот вопрос задает git commit
, например, когда идет обновление имени ветки.