Почему иногда необходимо использовать «git commit -a» вместо «git commit»? - PullRequest
4 голосов
/ 02 марта 2011

Играя с Git и GitHub, я обнаружил, что иногда

git commit -a

необходимо для фиксации измененного файла. (этот файл уже добавлен в проект).

Но иногда просто

git commit

будет работать. При использовании Mercurial команда hg com всегда работает, если это файл, который уже был добавлен ранее в репо. Так что мне интересно, зачем git иногда нужен -a? Слово «подготовка» встречается в некотором объяснении, но я не совсем понимаю концепцию подготовки и как она связана с фиксацией некоторых изменений в файле?

Ответы [ 5 ]

2 голосов
/ 02 марта 2011

Предположим, вы внесли два разных логических изменения в файл, но хотите зафиксировать только одно из них.Если «git commit» всегда фиксирует все файлы, о которых он знает, это будет невозможно.Таким образом, вам нужно подготовить каждое изменение перед выполнением коммита.Если вы «git add filename», вы вносите все изменения в этот файл.Кстати, «git stage» является синонимом «git add», и он может сделать действия более понятными, если вместо этого использовать «git stage».

Думайте о промежуточной области (указателе) как о промежуточной областимежду вашим рабочим каталогом и хранилищем.Команды «git add» и «git stage» перемещают объекты в индекс, а «git commit» перемещает их из индекса в репозиторий."git commit -a" делает оба шага одновременно.Часто очень полезно иметь возможность использовать постановку для уточнения ваших коммитов так, чтобы вы фиксировали именно то, что хотите.

1 голос
/ 03 марта 2011

Чтобы понять разницу между git commit и git commit -a, вам нужно знать о index в git, также известном как staging area .

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

Что действительно делает git add, так это «ставит» файл в файл или добавляет его текущее состояние к индексу. Неважно, был ли он изначально отслежен или нет, вы говорите: «В следующем коммите я хочу, чтобы этот файл присутствовал именно с этим содержимым». Важно понимать, что здесь записывается контент, который вы хотите добавить, а не имя файла - это означает, что если вы затем продолжите вносить изменения в файл после того, как добавили его в git add, вы увидите вывод из git status это иногда смущает людей, приходящих из других систем контроля версий:

$ git status
[...]
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   modified:   foo.txt
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   foo.txt

... но это имеет абсолютный смысл, если вы знаете об индексе. Вы можете увидеть изменения, которые вы уже поставили (то есть разницу между состоянием файлов в индексе и HEAD, который обычно является последним коммитом в ветви, над которой вы работаете) с:

$ git diff --cached

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

$ git diff

Так почему это так полезно? По сути, идея заключается в том, что история вашего проекта наиболее полезна, когда каждый коммит содержит логически сгруппированный набор изменений, которые вносят четко определенные улучшения в проект. Чем меньше вы можете сделать эти коммиты, тем лучше, поскольку позже замечательный инструмент git bisect может быстро помочь вам отследить, какие изменения привели к ошибке. Если вы не обладаете чрезмерной дисциплиной, то в процессе исправления ошибки вы часто будете заканчивать редактированием других файлов, которые вам не нужно менять, чтобы решить проблему, или в конечном итоге вы сможете решить две логически разные проблемы до того, как решив принять ваши изменения. В этих случаях индекс может помочь вам выделить эти изменения - просто git add в каждом файле, который содержит изменения, которые вы хотите внести в первый коммит, запустите git commit, затем сделайте то же самое, чтобы создать второй коммит. [1] * 1 029 *

Если вы привыкли делать это и вам нравится рабочий процесс, вам иногда придется просто захотеть внести некоторые изменений в файл, а не другие, и в этом случае вы захотите узнать о git add -p (а затем о его интерактивных опциях s и e!)

Однако, чтобы вернуться к первоначальному вопросу - что делает git commit -a иначе? По сути, он говорит: «Перед созданием этого коммита также поместите каждый файл, который был изменен (или удален) в его текущее состояние». Так что, если вы не думаете, что тщательное размещение файлов в индексе перед фиксацией полезно, вы можете просто использовать «git commit -a» все время. Тем не менее, я думаю, что одним из приятных моментов использования git является то, что он поощряет вас создавать красивые коммиты, и активное использование индекса очень помогает в этом. :)


Примечания:

Для простоты приведенного выше объяснения некоторые утверждения несколько приблизительны (например, я не упомянул, что индекс также хранит (не) исполняемое состояние файла, что он может иметь несколько версий во время слияния, и т. д.)

[1] Вы должны делать это осторожно, если хотите убедиться, что каждый коммит в вашей истории был должным образом протестирован - если это важно в вашем проекте, вы должны тестировать дерево при каждом новом коммите, прежде чем нажимать ...

1 голос
/ 02 марта 2011

См. Также статью " Вы могли изобрести git (а может, уже сделали!) ": это помогает, когда вы думаете об индексе как о "базе данных исправлений" .

Если вы «добавляете» файл (к «индексу», также известному как «область подготовки»), вы фактически добавляете патч, представленный эволюциями, сделанными в этом файле.
Если вы сделали новыйэволюции в том же файле после добавления его к индексу, вы фактически делаете новый патч (со всеми новыми эволюциями со времени последнего "git add"), и эти новыеНеобходимо добавить evolutions (в индекс, «базу данных патчей»), прежде чем вы сможете зафиксировать.
Или вы можете просто сделать git commit -a в этом случае.

1 голос
/ 02 марта 2011

Подробное описание справочной страницы в git commit описывает ее:

  • когда вы добавляете новый файл в git, вы делаете это с помощью git add. Это помечает файл, который будет добавлен к следующему commit (как и git rm для удаления файлов).
  • когда вы меняете файл, вы также можете сделать git add, чтобы пометить его для следующего коммита, но обычно это не так. В этом случае git commit -a сделает работу за вас:

    Скажите команде автоматически создавать файлы, которые были изменены и удалены, но новые файлы, о которых вы не сообщили git, не затрагиваются

Пример: , если вы хотите сделать коммит только с некоторыми файлами, которые были изменены (например, вы исправили ошибку, затрагивающую два файла (one.c, two.c) и удалили некоторые опечатки в других файлах и вы хотите, чтобы проверка исправлений исправлялась отдельно от проверки опечаток), вы должны сделать git add для каждого из файлов исправлений и затем зафиксировать:

git add one.c
git add two.c
git commit -m "bugfix checkin" 

Как только это будет сделано, вы фиксируете свои опечатки, используя

git commit -a -m "fixed typos"

Относительно постановки:
git commit фиксирует только те файлы, которые были помечены каким-либо образом. Это может произойти, например, через git add или git rm. Эта маркировка для коммита называется staging .

0 голосов
/ 02 марта 2011

Проверьте faq .Короче говоря, это делает git более гибким.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...