Почему выходные данные различаются при git diff против git diff - staged? - PullRequest
0 голосов
/ 23 декабря 2018

Зачем нам оба эти?И при каких обстоятельствах различаются выходные данные, которые они выдают в командной строке?

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

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

Я думаю, что вас вводят в заблуждение.Git не хранит изменения вообще.Все это кажется очень загадочным, пока вы не поймете, что Git просто хранит все в целости, но делает это странным образом.

То, что Git хранит постоянно

Первое и самое важное, Git не совсем точнохранить файлов .Это происходит, но это потому, что Git хранит коммитов , а каждый отдельный коммит содержит (все!) Файлы.То есть на более раннем этапе разработки вы или кто-то другой сказал Git: Вот это целое дерево файлов, некоторый набор папок / каталогов, содержащих файлы и подкаталоги, которые содержат больше файлов и подкаталогов и т. Д.на.Сделайте снимок того, как они все выглядят прямо сейчас. Этот снимок, вся эта копия всего, входит в новый коммит.

Далее, коммиты, как только они сделаны, в основном постоянны и полностью, полностью, 100% только для чтения.Вы не можете ничего изменить внутри коммита.Вы можете просто думать о них как о постоянных: единственное время, когда коммит действительно может уйти, - это если вы тщательно подготовитесь к тому, чтобы никто - ни вы, ни кто-либо другой - не могли найти позже, используя git reset или аналогичные инструменты.

По многим причинам, в том числе из-за отсутствия репозитория, он становится чрезвычайно толстым, если вы делаете много коммитов, которые продолжают использовать большинство старых версий большинства файлов, файлы, которые хранятся внутри коммитовхранятся в специальном сжатом формате Git-only.Поскольку файлы внутри коммитов заморожены, если новый коммит C9 точно такой же, как и предыдущий коммит C8 , за исключением одного файла, два коммита будут совместно использовать все идентичныефайлы тоже.

С чем Git позволяет вам работать временно

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

Git усложняет ситуацию своим индексом

Теперь наступает хитрый момент.Другие системы контроля версий могут остановиться здесь: у них тоже есть коммиты, которые сохраняют файлы навсегда в замороженном виде, и рабочее дерево, которое позволяет вам работать с файлами в обычной форме.Чтобы сделать новый коммит, эти другие системы управления версиями медленно, мучительно, одну за другой, берут каждый файл рабочего дерева, сжимают его, чтобы подготовить к замораживанию, и , а затем проверяют, не замерзло ли этофайл будет такой же, как старый.Если это так, они могут повторно использовать старый файл!Если нет, они делают все возможное, чтобы сохранить новый файл.Это ужасно медленно, и есть разные способы ускорить его, которые они используют в целом, но в этих не-Git системах контроля версий, после использования их команды "commit", вы часто можете встать и пойти выпить кофе,или прогуляться, или пообедать, или что-то в этом роде.

Git делает что-то радикально другое, и именно так git commit настолько быстр по сравнению с другими системами.Когда Git извлекает файлы из глубокой заморозки для помещения в ваше рабочее дерево, Git хранит своего рода полузамороженную - «слякотную», если хотите, копию каждого файла , готовую к работев следующий коммит.Первоначально все эти копии соответствуют замороженной копии коммита.

-сплошные копии файлов находятся в том, что Git называет, по-разному, index , staging area или cache , в зависимости от того, кто или какая частьGit делает призвание.Основное различие между этими индексными копиями каждого файла и замороженной копией в текущем коммите заключается в том, что зафиксированные копии действительно заморожены.Они не могут быть изменены.Копии индекса только почти заморожены: их можно изменить, записав новый файл в индекс вместо старого.

Что это значит,в конце концов, это то, что для каждого файла в коммите вы получаете не две, а три активных копии, когда вы указываете Git сделать этот коммит текущим, используя git checkout <em>somebranch</em>.(Эта проверка выбирает somebranch в качестве текущего имени ветви и, следовательно, также извлекает то, что Git называет tip commit как current commit. Для этого текущего коммита всегда есть имя: Git называет его HEAD.) Предположим, например, что коммит tip master имеет два файла с именами README.md и main.py:

   HEAD           index         work-tree
---------       ---------       ---------
README.md       README.md       README.md
main.py         main.py         main.py

На этом этапе все три копии каждого файла соответствуют друг другу .То есть все три README.md одинаковы, за исключением их формата: один в HEAD заморожен и предназначен только для Git;тот в индексе является полузамороженным и только для Git;и тот, что в вашем рабочем дереве, полезен и полезен для вас;но все три представляют одно и то же содержимое файла .То же самое касается трех копий main.py.

Теперь предположим, что вы изменили один (или оба) файла рабочего дерева.Например, предположим, что вы изменили свое рабочее дерево README.md.Давайте пометим его (2), чтобы указать, что он отличается, и пометим старые с (1), чтобы вспомнить, какие были старые:

    HEAD            index         work-tree
------------    ------------    ------------
README.md(1)    README.md(1)    README.md(2)
main.py(1)      main.py(1)      main.py(1)

Теперь вы можете попросить Git сравнить Индекс копирует каждый файл в копии рабочего дерева каждого файла, и на этот раз вы увидите изменение на README.md.

Когда вы запустите git add, вы действительно говорите Git: Возьмите копию рабочего дерева файлов, которые я добавляю, и подготовьте их к замораживанию. Git скопирует копию рабочего дерева README.md или main.py (или оба) обратно в индекс, Git-ifying содержимое, готовит их для следующего замораживания:

    HEAD            index         work-tree
------------    ------------    ------------
README.md(1)    README.md(2)    README.md(2)
main.py(1)      main.py(1)      main.py(1)

На этот раз, попросив Git сравнить index copy (всего) до рабочего дерева копия (всего) ничего не показывает!В конце концов, они одинаковы.Чтобы увидеть разницу, вы должны попросить Git сравнить фиксацию HEAD с индексом или фиксацию HEAD с рабочим деревом.Сейчас этого достаточно, потому что прямо сейчас индекс и рабочее дерево снова совпадают.

Обратите внимание, однако, что вы можете изменить копию рабочего дерева снова после использования git add.Предположим, вы изменили README.md еще раз, получив:

    HEAD            index         work-tree
------------    ------------    ------------
README.md(1)    README.md(2)    README.md(3)
main.py(1)      main.py(1)      main.py(1)

Теперь все три копии main.py совпадают, но все три копии README.md различны.Так что теперь имеет значение, используете ли вы Git сравни HEAD с индексом, или HEAD с рабочим деревом, или индекс с рабочим деревом: каждый из них покажет различное изменение до README.md.

Git делает новые коммиты из индекса

Когда и если вы решите сделать новый коммит - новый постоянный снимок всех файлов в том виде, в каком они есть сейчас - Git создает снимок нового коммита, используя полузамороженные файлы в индексе.Все, что глагол фиксации имеет к ним отношение, - это завершение процесса замораживания (который на техническом уровне состоит из создания дерева объектов для их хранения, но вам не нужно это знать).Поэтому git commit собирает ваше имя, адрес электронной почты, время, ваше сообщение журнала и хэш-идентификатор текущего коммита, замораживает индекс и объединяет все это в новый коммит.Новый коммит становится коммитом HEAD, так что теперь HEAD ссылается на новый коммит.Если старый коммит был C8 , а новый - C9 , HEAD имел обыкновение означать C8 , но теперь это означает C9 .

После завершения фиксации HEAD и индексные копии каждого файла автоматически соответствуют .Очевидно, что они должны, так как новый HEAD был сделан из индекса.Поэтому, если вы сделаете этот новый коммит с индексом, содержащим среднюю версию README.md, вы получите:

    HEAD            index         work-tree
------------    ------------    ------------
README.md(2)    README.md(2)    README.md(3)
main.py(1)      main.py(1)      main.py(1)

Обратите внимание, что Git полностью игнорировал рабочее дерево во время этого процесса!Есть способ сообщить git commit, что он должен смотреть на рабочее дерево и автоматически запустить git add, но давайте оставим это на потом.

Резюме этого конкретного разделахороший способ представить индекс: Индекс содержит следующий коммит, который вы предлагаете сделать. Команда git add означает: Обновить мой предложенный следующий коммит. Это объясняет, почему вы должны git add все время.

Git's diff глагол

Поскольку есть эти три одновременные, активные копии каждогофайл - один перманент, один предложенный для следующего коммита и тот, который вы действительно можете увидеть и работать с ним - Git нужен способ сравнить этих вещей.Глагол diff - это то, как вы просите Git сравнить две вещи, а его параметры - это то, как вы выбираете , что две вещи для сравнения:

  • git diff <em>commit-A commit-B</em> говоритGit: Извлечь снимок в коммите А во временную область;Извлеките снимок в коммите B во временную область, а затем сравните их и покажите, в чем отличие. В целом это полезно, но не так сильно при создании new , так как речь идет о существовании., замороженные, неизменяемые коммиты.

  • git diff - без опций или спецификаторов коммитов - сообщает Git: Сравнить индекс с рабочим деревом. Gitне смотрит на какой-либо фактический коммит, он просто смотрит на индекс - предложенный следующий коммит - и сравнивает с вашими используемыми копиями файлов.Когда что-то отличается, вы можете использовать git add, чтобы скопировать его в индекс.Так что это говорит вам о том, что вы могли бы git add, если хотите.

  • git diff --cached или git diff --staged - параметры имеют абсолютно одинаковое значение - сообщает Git: СравнитьHEAD фиксация индекса. На этот раз Git вообще не смотрит на ваше рабочее дерево.Он просто выясняет, что отличается между текущим коммитом и предложенным следующим коммитом .То есть это то, что было бы другим , если бы вы совершали действия прямо сейчас.

  • git diff HEAD (или, в более общем смысле, git diff <em>commit</em>) сообщает Git: Сравните то, что в коммите, который я назвал, например, HEAD, с тем, что находится в рабочем дереве. На этот раз Git игнорирует ваш индекс и просто использует конкретный коммит, такой какHEAD - и содержимое рабочего дерева.Это не так полезно, как сравнение HEAD-vs-index или index-vs-work-tree, но вы можете сделать это, если хотите.

Конечно, есть и другиевы можете захотеть сравнить любые два элемента, поэтому у git diff есть много вариантов.Но они являются основными интересными на данный момент.

git status работает два git diff s

Обратите внимание, что два самые полезные git diff с выше, когда вы активно разрабатываете, это git diff --cached, который говорит вам, что будет отличаться, если вы совершите прямо сейчас и git diff без опций, который говорит вам , что еще может отличаться , если вы запустили git add прямо сейчас.Команда git status, которую вы должны часто использовать, запускает обе эти разницы для вас!Он запускает их с внутренним флагом --name-status, так что вместо отображения реальных различий он просто показывает имя файла, если файл изменяется. 1

Давайте посмотрим, чтоеще раз: git status выполняет две git diff команды.Первый - git diff --cached, т. Е. Что отличается от предложенного коммита .Это изменения, подготовленные для фиксации .Вторым является простой git diff, то есть то, что отличается в индексе - предложенном коммите - и рабочем дереве.Это изменений, которые не предназначены для фиксации.

Итак, теперь вы знаете, что git status говорит вам, и когда вы захотите использовать git diff с или без --staged дляувидеть больше, чем просто имена файлов.Помните, что изменения, которые git diff показывает вам, это то, что Git вычисляет: файлы внутри индекса или в рабочем дереве являются полными, полными копиями.Они просто могут отличаться друг от друга и / или отличаться от полной, полной копии в HEAD.


1 Вместо этого может использоваться часть «status» --name-statusскажем, что файл добавлен - находится в индексе, но не в коммите HEAD, например.Или, в некоторых случаях, он может сказать, что файл переименован или имеет некоторые другие вспомогательные изменения, но давайте не будем вдаваться в подробности.

0 голосов
/ 23 декабря 2018

git diff сообщает о неустановленных изменениях между текущими файлами и последним коммитом.git diff --cached сообщает о поэтапных изменениях (т. Е. Изменениях, которые вы git add редактировали).

...