Какая польза от двухэтапного процесса коммита git?

175

Я изучаю git и заметил, что он имеет двухэтапный процесс коммита:

  1. git add <files>
  2. git commit

Первый шаг помещает изменения в так называемую «область подготовки» или «индекс».

Меня интересует, почему принимается это дизайнерское решение и в чем его преимущества?

Кроме того, как пользователь git вы делаете это или просто используете git commit -a?

Я спрашиваю об этом, потому что я из bzr (Bazaar), который не имеет этой функции.

thomasrutter
источник
3
+1 за вопрос. Я использую Tortoise SVN, который имеет тот же подход, и я никогда не понимал, почему.
DPD
3
Площадка не так уж необычна. Эквивалент, скажем, в TFS, будет проверять или снимать флажок рядом с файлом перед регистрацией. Только проверенные файлы будут зафиксированы. Разница с Git заключается в том, что если вы используете git add -p, вы можете выбрать фиксацию одного фрагмента файла, но не фиксацию другого фрагмента того же файла .
Kyralessa
Я обнаружил, что эта ссылка суммирует большую часть того, на что здесь был дан ответ, и добавляет еще несколько вариантов использования, чтобы оправдать необходимость постановки.
Веверке
2
На этот вопрос на самом деле уже дан ответ, но здесь также есть одно хорошее объяснение: stackoverflow.com/questions/4878358/…
guitar_freak
1
Не забудь git statusи возможно git push.
user949300

Ответы:

83

Разделить работу на отдельные коммиты. Возможно, вы много раз открывали файл для написания однострочного исправления, но в то же время вы замечали, что форматирование было неправильным, некоторая документация может быть улучшена или какое-то другое несвязанное исправление. С другими RCS вы должны были бы записать это или зафиксировать в памяти, закончить исправление, к которому вы пришли, зафиксировать это, а затем вернуться, чтобы исправить другие вещи (или создать коммит из грязи с несвязанными вещами) , С Git вы просто исправляете все это сразу, а stage + фиксирует одну строку отдельно, с помощью git add -iили git-gui.

Не ломай сборку. Вы работаете над сложной модификацией. Таким образом, вы пробуете разные вещи, некоторые из которых работают лучше, чем другие, некоторые ломают вещи. С Git вы бы ставили вещи, когда модификация делала вещи лучше, и checkout(или немного улучшали ), когда модификация не работала. Вам не нужно полагаться на функции отмены редактора, вы можете checkoutиспользовать весь репозиторий, а не просто файл за файлом, и любые ошибки на уровне файлов (такие как удаление файла, который не был зафиксирован, или сохранение + закрытие после плохая модификация) не приводит к потере большого количества работы.

l0b0
источник
3
Исходя из DVCS (bzr), который не имеет этой функции, это звучит очень похоже на то, что я в настоящее время достигаю благодаря комбинации либерального использования буферов отмены моего редактора, команды "revert <file>" и выборочных фиксаций (" совершить <файл> "). Похоже, эта особенность git может быть более методичной.
Томасруттер
1
Что касается "других RCS", это не обязательно верно. Фактически, вы можете реализовать те же функции в Mercurial, используя патчи .
Лусио Пайва
1
@ l0b0, о твоем втором пункте. Если бы был только одноэтапный коммит, вы могли бы просто зафиксировать изменения (которые вы используете с git add) непосредственно как коммит. Если бы вы узнали, что сделали что-то не так, вы просто удалили коммит и вернулись туда, где вы были до того, как сделали коммит. С концепцией постановки, вы не просто делаете это, но добавляете больше сложности?
alpha_989
Ваш первый пункт имеет смысл, хотя я до сих пор не использовал его. Теоретически, почему вы не можете сделать что-то вроде a git add -iс одноступенчатым коммитом? Вы должны просто выбрать группу файлов (или строк в файлах), связанных с одной функцией, и выполнить коммит. Затем вы вернетесь и сделаете второй коммит, связанный с другой функцией ..
alpha_989
@thomasrutter, из вашего заявления кажется, что вы предлагаете, чтобы область подготовки создавала «точки отмены вручную». В VIM с постоянным откатом вы можете получить неограниченную историю очень надежно. Это также отслеживается автоматически по git-branchтипу ( jovicailic.org/2017/04/vim-persistent-undo ). Далее ваша история отмен автоматически отслеживается каждый раз, когда вы переходите в обычный режим. Таким образом, это уменьшает ваше умственное бремя необходимости создавать «точки отмены вручную». Почему использование буферов отмены ваших редакторов не так методично?
alpha_989
65

Одним из преимуществ для меня является возможность «добавлять» файлы постепенно. Перед фиксацией я просматриваю каждый файл. Как только файл просмотрен, я добавляю его. Когда я git statusили git diff, git показывает мне только файлы, которые были изменены и еще не были добавлены. Когда я проверил все файлы и добавил их, я могу сделать коммит.

Так что да, я считаю, что место для постановки очень полезно.

И нет, я никогда не использую git commit -a. Тем не менее, я часто использую git add -u. Таким образом, я все еще могу визуализировать, что должно быть совершено.

Дэвид
источник
2
Именно так. Преимущество - гораздо более точный контроль над тем, что вы делаете.
Джош К
что происходит, когда вы создаете один файл несколько раз? это "сливается" в области постановки?
m4l490n
21

Преимущество довольно простое: оно дает вам полный контроль над тем, какие файлы вы хотите зафиксировать, когда. В этом отношении вы можете использовать, git add -pчтобы контролировать, какие строки вы хотите зафиксировать.

Рейн Хенрикс
источник
2
Мне всегда было интересно, как это сделать. Хотелось бы, чтобы был файл, .gitignorelinesчтобы вы могли вносить локальные изменения в отдельные строки, которые могли бы пережить коммиты и остаться без изменений
Алекс
3
@ReinHenrichs, подумайте о конфигурационных файлах, которые должны быть изменены каждым разработчиком.
Ян
1
@Ian Значит, часть файла изменяется нечасто и используется совместно, а часть файла часто изменяется несовместимыми способами и не используется совместно? Поддержка этого ложного выздоровления определенно звучит как анти-фича.
Рейн Хенрикс
1
@ReinHenrichs, да, и это очень часто встречается, когда файл содержит имя сервера базы данных, и у каждого разработчика есть собственная база данных.
Ян
4
@Ian Ваша проблема действительно в том, что у вас есть файл, который, как предполагается, является конфигурацией для приложения, также содержит некоторую конкретную конфигурацию машины / устройства. Все системы конфигурации, о которых я знаю, позволяют разбить их на несколько файлов. Так, например, у вас есть ваш, app.confкоторый содержит материал, которым вы хотите поделиться, а затем тот, db.confкоторый вы просто поместили в список .gitignore. Задача решена. Если вы используете что-то запатентованное, вам действительно стоит задуматься о том, чтобы получить что-то настолько простое. Или поместите его через препроцессор в событие перед сборкой. Множество решений есть.
Aidiakapi
1

Одним из преимуществ, которые мне нравятся, является возможность совершать часть изменений. Т.е., используя git add -e. Я делаю не так часто, как следовало бы, и команда git add -e позволяет мне в какой-то степени распутывать мои изменения.

leed25d
источник