Я новичок в управлении версиями и понимаю, что «фиксация» - это, по сути, создание резервной копии при обновлении новой «текущей» версии того, над чем вы работаете.
Я не понимаю, для чего постановка с практической точки зрения. Постановка чего-то, что существует только по названию, или служит определенной цели? Когда вы фиксируете, он все равно все равно фиксирует, верно?
Изменить: я думаю, что могу запутать терминологию. «Поэтапный» файл - это то же самое, что «отслеживаемый» файл?
Ответы:
Когда вы фиксируете, он фиксирует только изменения в индексе («поэтапные» файлы). Для этого есть много применений, но наиболее очевидным является разбиение ваших рабочих изменений на более мелкие, автономные части. Возможно, вы исправили ошибку при реализации функции. Вы можете
git add
просто этот файл (илиgit add -p
добавить только часть файла!), А затем зафиксировать это исправление, прежде чем фиксировать все остальное. Если вы используете,git commit -a
то вы просто форсируетеadd
все прямо перед фиксацией. Не используйте,-a
если вы хотите использовать промежуточные файлы.Вы также можете рассматривать подготовленные файлы как промежуточную рабочую копию с помощью
--cached
многих команд. Например,git diff --cached
он покажет вам, чем отличается этап от,HEAD
чтобы вы могли видеть, что собираетесь зафиксировать, не добавляя другие рабочие изменения.источник
git reset --hard
.git diff --staged
проверьте, какие файлы вы изменили и где, и начните вносить другие изменения.источник
Практическая цель постановки - логическое разделение коммитов файлов.
Поскольку подготовка позволяет вам продолжать редактировать файлы / рабочий каталог и делать коммиты по частям, когда вы думаете, что все готово, вы можете использовать отдельные этапы для логически не связанных правок.
Предположим , у вас есть 4 файла
fileA.html
,fileB.html
,fileC.html
иfileD.html
. Вы делаете изменения для всех 4 -х файлов и готовы совершить , но изменения вfileA.html
иfileB.html
логически связаны между собой (например, тем же новой реализация функции в обеих файлах) , а измененияfileC.html
иfileD.html
являются самостоятельными и логически связаны с предыдущими файлами. Вы можете первый этап файлыfileA.html
иfileB.html
и зафиксируйте их.Затем на следующем этапе вы вносите изменения в оставшиеся два файла и фиксируете их.
источник
git commit -m "Implemented new feature XYZ" fileA.html fileB.html
будет работать нормально и без команд git add. Я пришел из мира подрывной деятельности, где постановка не является концепцией, поэтому я не уверен в полезности постановки с помощью gitЛегче понять использование команд git,
add
иcommit
если вы представите, что файл журнала поддерживается в вашем репозитории на Github. Типичный файл журнала проекта для меня может выглядеть так:Обычно я начинаю свой день с
git pull
просьбы и заканчиваю егоgit push
просьбой. Итак, все внутри дневной записи соответствует тому, что происходит между ними. В течение дня я выполняю одну или несколько логических задач , требующих изменения нескольких файлов. Файлы, отредактированные во время этой задачи, перечислены в указателе.Каждая из этих подзадач (здесь задача A и задача B) - это отдельные коммиты. Команда
git add
добавляет файлы в список «Индекс измененных файлов». Этот процесс также называют постановкой. Командаgit commit
записывает / завершает изменения и соответствующий список индексов вместе с настраиваемым сообщением.Помните, что вы по-прежнему изменяете только локальную копию своего репозитория, а не копию на Github. После этого, только когда вы выполните «git push», все эти записанные изменения вместе с вашими индексными файлами для каждого коммита будут зарегистрированы в основном репозитории (на Github).
В качестве примера, чтобы получить вторую запись в этом воображаемом файле журнала, я бы сделал:
В двух словах,
git add
иgit commit
позволяет вам разбить изменения в основном репозитории на систематические логические подмены. Как указывалось в других ответах и комментариях, их, конечно же, можно использовать гораздо больше. Однако это одно из наиболее распространенных применений и движущий принцип, лежащий в основе Git как многоступенчатой системы контроля версий, в отличие от других популярных систем, таких как Svn.источник
Чтобы расширить ответ Бена Джексона , и это нормально, давайте внимательно рассмотрим исходный вопрос. (Смотрите его ответ, чтобы узнать, зачем беспокоить типовые вопросы; это больше о том, что происходит .)
Это не совсем так . Резервное копирование и контроль версий, безусловно, связаны - насколько сильно зависит от некоторых вещей, которые в какой-то степени являются предметом мнения, - но, безусловно, есть некоторые различия, хотя бы по назначению: резервные копии обычно предназначены для аварийного восстановления (сбой машины, пожар уничтожает все здание, включая все носители информации и т. д.). Контроль версий обычно предназначен для более детального взаимодействия и предлагает функции, которых нет в резервных копиях. Резервные копии обычно хранятся в течение некоторого времени, а затем отбрасываются как «слишком старые»: все, что имеет значение, - это более свежие резервные копии. Контроль версий обычно сохраняет каждую подтвержденную версию навсегда.
Да и нет. Дизайн Git здесь несколько своеобразный. Существуют системы контроля версий, которые не требуют отдельного этапа подготовки. Например, Mercurial, который в остальном очень похож на Git с точки зрения использования, не требует отдельного
hg add
шага, кроме самого первого, который вводит полностью новый файл. В Mercurial вы используетеhg
команду, которая выбирает какую-то фиксацию, затем вы делаете свою работу, затем запускаетеhg commit
, и все готово. В Git вы используетеgit checkout
, 1, затем выполняете свою работу, затем запускаетеgit add
, а затемgit commit
. Почему лишняяgit add
ступенька?Секрет здесь в том, что Git называет, по-разному, индексом или промежуточной областью , а иногда - редко в наши дни - кешем . Все это названия одного и того же.
Нет, но они связаны. Отслеживаются файл один , который существует в индексе Git и . Чтобы правильно понять индекс, хорошо начать с понимания коммитов.
Начиная с версии Git 2.23, вы можете использовать
git switch
вместоgit checkout
. В данном конкретном случае эти две команды делают одно и то же. Новая команда существует потому, чтоgit checkout
она перегружена множеством вещей; они были разделены на две отдельные командыgit switch
иgit restore
, чтобы было проще и безопаснее использовать Git.Совершает
В Git коммит сохраняет полный снимок каждого файла, о котором знает Git. (О каких файлах знает Git? Мы увидим это в следующем разделе.) Эти снимки хранятся в специальной, доступной только для чтения, только Git, сжатой и дедуплицированной форме, которую, как правило, может читать только сам Git. . (В каждом коммите есть больше вещей, чем просто этот снимок, но это все, что мы здесь рассмотрим.)
Дедупликация помогает с пространством: обычно мы изменяем только несколько файлов, а затем делаем новую фиксацию. Таким образом, большинство файлов в коммите в основном такие же, как файлы в предыдущем коммите. Просто повторно используя эти файлы напрямую, Git экономит много места: если мы коснулись только одного файла, новая фиксация займет место только для одной новой копии. Даже в этом случае он сжимается - иногда очень сжат, хотя на самом деле это происходит позже, - так что
.git
каталог может быть меньше, чем файлы, которые он содержит, после того, как они расширены до обычных повседневных файлов. Дедупликация безопасна, поскольку зафиксированные файлы замораживаются навсегда. Никто не может изменить один, поэтому фиксации могут зависеть от копий друг друга.Однако, поскольку хранящиеся файлы находятся в этом специальном, замороженном на все время формате, предназначенном только для Git, Git должен расширять каждый файл в обычную повседневную копию. Эта обычная копия не является копией Git : это ваша копия, которую вы можете использовать. Git просто напишет им, когда вы ему скажете, чтобы у вас были копии для работы. Эти используемые копии находятся в вашем рабочем дереве или рабочем дереве .
Это означает, что когда вы проверяете конкретный коммит, автоматически создаются две копии каждого файла:
В текущем коммите Git имеет замороженную на все время копию Git-ified . Вы не можете изменить эту копию (хотя вы, конечно, можете выбрать другую фиксацию или сделать новую фиксацию).
В вашем рабочем дереве есть копия в нормальном формате. Вы можете делать с этим все, что захотите, используя любую из команд на вашем компьютере.
Другие системы контроля версий (включая Mercurial, упомянутые выше) останавливаются на этих двух копиях. Вы просто изменяете свою копию рабочего дерева, а затем фиксируете. Гит ... нет.
Индекс
Между этими двумя копиями Git хранит третью копию 2 каждого файла. Эта третья копия находится в замороженном формате , но, в отличие от замороженной копии в фиксации, вы можете изменить ее. Чтобы изменить это, вы используете
git add
.Команда
git add
означает, что индексная копия файла должна соответствовать копии рабочего дерева . То есть вы говорите Git: замените замороженный формат, дедуплицированную копию, которая сейчас находится в индексе, сжав мою обновленную копию рабочего дерева, дедуплицируя ее и подготовив ее к замораживанию в новом коммите. Если вы не используетеgit add
, индекс по-прежнему содержит копию в замороженном формате из текущего коммита.Когда вы запускаете
git commit
, Git упаковывает все, что находится в индексе, сразу для использования в качестве нового снимка. Поскольку он уже находится в замороженном формате и предварительно дедуплицирован, Git не нужно выполнять много дополнительной работы.Это также объясняет, что такое неотслеживаемые файлы . Неотслеживаемый файл представляет собой файл , который находится в рабочем дереве , но не в индексе Git и сейчас . Неважно, как файл оказался в таком состоянии. Может быть, вы скопировали его из другого места на своем компьютере в свое рабочее дерево. Может быть, вы создали его здесь свежим. Возможно, в индексе Git была копия, но вы удалили эту копию с помощью
git rm --cached
. Так или иначе, в вашем рабочем дереве есть копия, но ее нет в индексе Git. Если вы сделаете новую фиксацию сейчас, этого файла не будет в новой фиксации.Обратите внимание, что
git checkout
изначально индекс Git заполняется из проверенной фиксации. Итак, индекс начинает соответствовать фиксации. Git также заполняет ваше рабочее дерево из того же источника. Итак, изначально все три совпадают. Когда вы меняете файлы в своем рабочем дереве иgit add
их, ну, теперь индекс и ваше рабочее дерево совпадают. Затем вы запускаете,git commit
и Git делает новую фиксацию из индекса, и теперь все три снова совпадают.Поскольку Git делает новые коммиты из индекса, мы можем сказать это так: индекс Git содержит следующую фиксацию, которую вы планируете сделать. Это игнорирует расширенную роль, которую индекс Git берет на себя во время конфликтного слияния, но мы все равно хотели бы игнорировать это сейчас. :-)
Вот и все, но это все еще довольно сложно! Это особенно сложно, потому что нет простого способа точно увидеть, что находится в индексе Git. 3 Но это команда Git , которая говорит вам , что происходит, таким образом , что это очень полезно, и что команда
git status
.2 Технически это вообще не копия . Вместо этого это ссылка на файл Git-ified, предварительно дедуплицированный и все такое. Здесь также есть больше вещей, таких как режим, имя файла, номер стадии и некоторые данные кеша, чтобы Git работал быстрее. Но если вы не начнете работать с некоторыми низкоуровневыми командами Git -
git ls-files --stage
иgit update-index
в частности - вы можете просто думать об этом как о копии.3 Команда
git ls-files --stage
покажет вам имена и промежуточные номера каждого файла в индексе Git, но обычно это все равно не очень полезно.git status
На
git status
самом деле команда работает, выполняяgit diff
за вас две отдельные команды (а также делая некоторые другие полезные вещи, например, сообщая вам, в какой ветке вы находитесь).Первый
git diff
сравнивает текущую фиксацию - которая, помните, заморожена на все время - с тем, что есть в индексе Git. Для одинаковых файлов Git вообще ничего не скажет. Для разных файлов Git сообщит вам, что этот файл подготовлен для фиксации . Это включает в себя все новые файлы, если обязательство неsub.py
в нем, но индекс действительно естьsub.py
в нем, то добавляется, и этот файл любые удаленные файлы, которые были (и есть) в фиксации , но не в индекса уже нет (git rm
, возможно).Второй
git diff
сравнивает все файлы в индексе Git с файлами в вашем рабочем дереве. Для одинаковых файлов Git вообще ничего не говорит. Для разных файлов Git сообщит вам, что этот файл не предназначен для фиксации . В отличие от первого сравнения, этот конкретный список не включает файлы, которые являются полностью новыми: если файлuntracked
существует в вашем рабочем дереве, но не в индексе Git, Git просто добавляет его в список неотслеживаемых файлов . 4В конце, собрав эти неотслеживаемые файлы в списке, также
git status
будут объявлены имена этих файлов, но есть специальное исключение: если имя файла указано в.gitignore
файле, этот последний список будет подавлен. Обратите внимание, что перечисление отслеживаемого файла - того, что находится в индексе Git -.gitignore
здесь не имеет никакого эффекта : файл находится в индексе, поэтому он сравнивается и фиксируется, даже если он указан в.gitignore
. Файл игнорирования подавляет только жалобы на "неотслеживаемый файл". 54 При использовании краткой версии
git status
-git status -s
- неотслеживаемые файлы не отделены друг от друга, но принцип тот же.git status
Подобное накопление файлов также позволяет суммировать имена нескольких неотслеживаемых файлов, иногда просто печатая имя каталога. Чтобы получить полный список, используйтеgit status -uall
илиgit status -u
.5 Листинг файла также заставляет массово добавлять множество файловых операций, таких как неотслеживаемый файл
git add .
илиgit add *
пропускать его. Эта часть становится немного сложнее, так как вы можете использоватьgit add --force
для добавления файла, который обычно пропускается. Есть несколько других обычно незначительных особых случаев, все из которых складываются в это: файл.gitignore
может называться более правильно.git-do-not-complain-about-these-untracked-files-and-do-not-auto-add-them
или что-то столь же громоздкое. Но это слишком смешно, так.gitignore
оно и есть.git add -u
,git commit -a
и т. д.Здесь есть несколько удобных ярлыков:
git add .
добавит все обновленные файлы в текущий каталог и любой подкаталог. Это соблюдается.gitignore
, поэтому, если файл, который в настоящее время не отслеживается, не получил жалобуgit status
, он не будет добавлен автоматически.git add -u
автоматически добавит все обновленные файлы в любое место вашего рабочего дерева . 6 Это влияет только на отслеживаемые файлы. Обратите внимание, что если вы удалили копию рабочего дерева, это также удалит копию индекса (git add
это как часть его соответствия индексу с деревом работы ).git add -A
это похоже на бегgit add .
с верхнего уровня вашего рабочего дерева (но см. сноску 6).Помимо этого, вы можете бегать
git commit -a
, что примерно эквивалентно 7 бегуgit add -u
и затемgit commit
. То есть это дает вам то же поведение, которое удобно в Mercurial.Я обычно не рекомендую использовать этот
git commit -a
шаблон: я считаю, что его лучше использоватьgit status
почаще, внимательно посмотрите на вывод и, если статус не соответствует вашим ожиданиям, выясните, почему это так. Приgit commit -a
использовании слишком легко случайно изменить файл и зафиксировать изменение, которое вы не собирались фиксировать. Но это в основном вопрос вкуса / мнения.6 Если ваша версия Git предшествует Git 2.0, будьте осторожны:
git add -u
работает только с текущим каталогом и подкаталогами, поэтому вы должны сначала подняться на верхний уровень своего рабочего дерева. Уgit add -A
варианта есть аналогичная проблема.7 Я говорю примерно эквивалентно, потому что на
git commit -a
самом деле работает путем создания дополнительного индекса и использования этого другого индекса для фиксации. Если фиксация работает , вы получите тот же эффект, что и выполнениеgit add -u && git commit
. Если фиксация не работает - если вы заставляете Git пропускать фиксацию любым из множества способов, которыми вы можете это сделать, - после этого никакие файлы не обрабатываютсяgit add
, потому что Git выбрасывает временный дополнительный индекс и возвращается к использованию основного индекса .Если вы воспользуетесь
git commit --only
здесь , возникнут дополнительные сложности . В этом случае Git создает третий индекс, и все становится очень сложно, особенно если вы используете перехватчики перед фиксацией. Это еще одна причина использовать отдельныеgit add
операции.источник
Промежуточная область помогает нам создавать коммиты с большей гибкостью. Под обработкой я подразумеваю разбиение коммитов на логические единицы. Это очень важно, если вы хотите поддерживать программное обеспечение. Самый очевидный способ добиться этого:
Вы можете работать над несколькими функциями / ошибками в одном рабочем каталоге и при этом создавать значимые коммиты. Также очень удобно иметь единый рабочий каталог, содержащий всю нашу активную работу. (Это можно сделать без промежуточной области, только при условии, что изменения никогда не перекрывают файл. Кроме того, вы должны вручную отслеживать, перекрываются ли они)
Вы можете найти больше примеров здесь: Использование индекса
И что самое приятное, преимущества не ограничиваются этим списком рабочих процессов. Если все же появится уникальный рабочий процесс, вы можете быть почти уверены, что промежуточная область вам поможет.
источник
Я вижу смысл в использовании stage для уменьшения размера коммитов, о чем упоминали @Ben Jackson и @Tapashee Tabassum Urmi, и иногда я использую его для этой цели, но в основном я использую его для увеличения размера моих коммитов! вот моя точка зрения:
Скажем, я хочу добавить небольшую функцию, которая требует нескольких небольших шагов. Я не вижу смысла в том, чтобы делать отдельные коммиты для небольших шагов и заполнять мою временную шкалу. Однако я хочу сохранить каждый шаг и вернуться при необходимости,
Я просто накладываю более мелкие шаги друг на друга, и когда чувствую, что это достойно фиксации, я совершаю. Таким образом, я удаляю ненужные коммиты с временной шкалы, но могу отменить (оформить заказ) последний шаг.
Я вижу другие способы сделать это (упрощая историю git), которые вы можете использовать в зависимости от ваших предпочтений:
источник
Это похоже на флажок, который дает возможность выбирать, какие файлы фиксировать.
например, если я редактировал
fileA.txt
и.fileB.txt
Но я хочу зафиксировать измененияfileA.txt
только. потому что я еще не закончилfileB.txt
.Я могу просто использовать
git add fileA.txt
и зафиксировать использованиеgit commit -m "changed fileA.txt"
и продолжить работу сfileB.txt
а после завершения я могуfileB.txt
легко фиксироватьисточник