В Git, какова цель индекса?

Я понимаю, что типичный рабочий процесс Git состоит из трех этапов: (изменить файлы в рабочем дереве) -> (изменить индекс с помощью git add/rm/etc) -> (запустить git commit).

Однако, почему Git не рассматривает дерево работы как область подготовки? Например, вы изменяете файл, и он автоматически "ставится" для фиксации, если вы не указали git не ставить его. Это скорее подход отказа, а не отказа, который имеет смысл для меня, потому что 99% файлов в вашем рабочем дереве будут зафиксированы. Это также сделает весь git stash механизм избыточен, так как вы можете просто создать временную ветку из вашего рабочего дерева, а не save тайник к apply позже.

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

2 ответа

На сайте Git действительно есть хорошее объяснение того, что такое промежуточная область, причина, по которой она существует, преимущества, которые она предлагает, и способ обойти ее при совершении коммитов.

Взято с http://git-scm.com/about/staging-area

Плацдарм

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

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

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

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

Надеюсь это поможет. Ура!

Mercurial - это, по сути, "мерзавец без индекса", и, как таковой, является доказательством того, что это можно сделать. Любой вопрос "почему" попадает во множество серых областей. Но вот что обеспечивает индекс:

  • Очень быстрый "git commit": индекс уже содержит следующий коммит; его просто нужно переформатировать в древовидные объекты и конечный объект фиксации.

  • Промежуточная область, так что вы можете сделать коммит не соответствующим рабочему каталогу. (Не все считают, что это хорошо.) В Mercurial для фиксации файлов A а также C опуская рабочую версию B, вы должны выполнить команду commit с именами всех файлов, которые будут включены (или исключены), прописаны все сразу. В git вы можете настроить сцену, запустить git diff --cached (или же --staged), решить, правильно ли это или нужно настроить, git add или же git reset чтобы настроить сцену, запустить другой git diff --cached, и так далее. (В Mercurial я обнаружил, что гораздо проще достичь того же самого путем удаления всех "нежелательных" изменений из области хранилища, hg commit, затем перенесите эти изменения обратно.)

  • Легкость внесения изменений в неопубликованные коммиты. Привыкнув к области подготовки и внесению поправок в git, когда я сделал поправку в Mercurial, я с удивлением обнаружил, что все мое текущее дерево работ стало новым исправленным коммитом. (Я не должен был удивляться, но я был! Опять же, это восходит к другой философии: в hg вы полностью удаляете части "еще не готовы" из репо, чтобы они не проникли внутрь.)

  • Хитрые хаки. (Опять же, не все считают, что это хорошо.) В частности, вы можете установить биты в индексе, такие как "предполагать неизменным" или "намерение добавить", которые влияют на будущие коммиты (опять же, потому что индекс, в некотором смысле, " следующий коммит строится ").

  • Способ удерживать и, следовательно, легко получать доступ к файлам, подлежащим объединению, в случае конфликта объединения.

Этот последний заслуживает дополнительного объяснения. Предположим, вы сливаетесь old-fix в feature, И в feature, файл был переименован FA, Слияние понимает, что ему нужно получить файл (под старым именем) из ветки old-fix, а также FA от featureи объединить их. Но возникает конфликт слияния, и ваша система версий останавливается и нуждается в вашей помощи в завершении слияния.

Теперь предположим, что вы хотите посмотреть на версию FA в old-fixсравнивая это с FA в feature, Если вы буквально зацените ветку old-fixнет файла с именем FA! Но git хранит его в индексе, так что вы можете видеть его, не зная, каким было старое имя, так как индекс создает следующий коммит (который сохраняет новый FA название).

Вы также можете посмотреть на feature версия, хотя, конечно, это проще, так как вы знаете, что она называется FA, Но это есть в индексе. Кроме того, общая (базовая) версия (которая также находится под тем же старым именем, что и в old-fix) находится в индексе, как отмечено в gitrevisions:

A colon, optionally followed by a stage number (0 to 3) and a
colon, followed by a path, names a blob object in the index at the
given path. A missing stage number (and the colon that follows it)
names a stage 0 entry. During a merge, stage 1 is the common
ancestor, stage 2 is the target branch's version (typically the
current branch), and stage 3 is the version from the branch which
is being merged.

То есть, :1:FA является общим предком для файла FA, :2:FA является featureверсия, и :3:FA является old-fixверсия

Все эти точные настройки приводят к ошибкам для новичков (или даже экспертов), поэтому версия без индекса для Mercurial может лучше подойти вашей работе. Однако, используя git commit -aПо сути, вы получаете то же поведение, что и с Mercurial, поэтому вы часто можете игнорировать его, пока не захотите.

Другие вопросы по тегам