Я использую Git уже пару месяцев в проекте с одним другим разработчиком. У меня есть несколько лет опыта работы с SVN , поэтому я полагаю, что я привнес много багажа в отношения.
Я слышал, что Git отлично подходит для ветвления и слияния, и пока я просто не вижу этого. Конечно, ветвление просто невероятно, но когда я пытаюсь слиться, все идет к черту. Теперь я привык к этому из SVN, но мне кажется, что я просто обменял одну систему контроля версий на другую.
Мой партнер говорит мне, что мои проблемы проистекают из моего желания слиться волей-неволей, и что во многих ситуациях мне следует использовать rebase вместо слияния. Например, вот рабочий процесс, который он заложил:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature
git checkout master
git merge my_new_feature
По сути, создайте ветвь объектов, ВСЕГДА перебирайте с мастера на ветку и сливайте с ветки обратно на ветку. Важно отметить, что филиал всегда остается локальным.
Вот рабочий процесс, с которого я начал
clone remote repository
create my_new_feature branch on remote repository
git checkout -b --track my_new_feature origin/my_new_feature
..work, commit, push to origin/my_new_feature
git merge master (to get some changes that my partner added)
..work, commit, push to origin/my_new_feature
git merge master
..finish my_new_feature, push to origin/my_new_feature
git checkout master
git merge my_new_feature
delete remote branch
delete local branch
Есть два существенных различия (я думаю): я использую слияние всегда, а не перебазирование, и я помещаю свою ветвь функций (и мои коммиты ветви функций) в удаленный репозиторий.
Я рассуждаю об удаленной ветке так, что я хочу, чтобы моя работа поддерживалась во время работы. Наш репозиторий автоматически резервируется и может быть восстановлен, если что-то пойдет не так. Мой ноутбук не, или не так тщательно. Поэтому я ненавижу иметь код на моем ноутбуке, который не отражен где-то еще.
Мое рассуждение о слиянии вместо rebase заключается в том, что слияние кажется стандартным, а rebase - расширенной функцией. У меня такое ощущение, что я пытаюсь не продвинутая настройка, поэтому ребаз должен быть ненужным. Я даже просмотрел новую книгу «Прагматическое программирование» по Git, и в ней подробно рассматриваются слияния и едва упоминается ребазинг.
Во всяком случае, я следил за своим рабочим процессом в недавней ветке, и когда я попытался объединить его с мастером, все пошло к черту. Было множество конфликтов с вещами, которые не должны были иметь значения. Конфликты просто не имели смысла для меня. Мне потребовался день, чтобы все уладить, и в итоге я вынужден был принудительно подтолкнуть удаленного мастера, поскольку мой локальный мастер разрешил все конфликты, но удаленный все еще не был доволен.
Каков «правильный» рабочий процесс для чего-то подобного? Git должен сделать ветвление и слияние очень легким, и я просто не вижу этого.
Обновление 2011-04-15
Это, кажется, очень популярный вопрос, поэтому я подумала, что обновлю свой двухлетний опыт с тех пор, как я его впервые спросила.
Оказывается, исходный рабочий процесс корректен, по крайней мере, в нашем случае. Другими словами, это то, что мы делаем, и это работает:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge my_new_feature
На самом деле, наш рабочий процесс немного отличается, так как мы склонны делать сквош-слияния вместо сырых слияний. ( Примечание: это противоречиво, см. Ниже. ) Это позволяет нам превратить всю нашу ветку объектов в один коммит на master. Затем мы удаляем нашу ветку функций. Это позволяет нам логически структурировать наши коммиты на master, даже если они немного запутаны в наших ветках. Итак, вот что мы делаем:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge --squash my_new_feature
git commit -m "added my_new_feature"
git branch -D my_new_feature
Противоречие слияния сквоша - Как указали несколько комментаторов, слияние сквоша отбросит всю историю вашей ветки. Как следует из названия, он сводит все коммиты в один. Для небольших функций это имеет смысл, поскольку сводит их в единый пакет. Для более крупных функций это, вероятно, не очень хорошая идея, особенно если ваши отдельные коммиты уже атомарны. Это действительно сводится к личным предпочтениям.
Github и Bitbucket (другие?) Запросы на извлечение - Если вам интересно, как слияние / перебазирование связано с запросами на извлечение, я рекомендую выполнить все вышеописанные шаги до тех пор, пока вы не будете готовы к слиянию с мастером. Вместо ручного слияния с git, вы просто принимаете пиар. Обратите внимание, что это не будет выполнять слияние с помощью сквоша (по крайней мере, по умолчанию), но без сквоша, без ускоренной перемотки является принятым соглашением о слиянии в сообществе запросов на извлечение (насколько я знаю). В частности, это работает так:
clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git push # May need to force push
...submit PR, wait for a review, make any changes requested for the PR
git rebase master
git push # Will probably need to force push (-f), due to previous rebases from master
...accept the PR, most likely also deleting the feature branch in the process
git checkout master
git branch -d my_new_feature
git remote prune origin
Я полюбил Git и больше не хочу возвращаться в SVN. Если вы боретесь, просто придерживайтесь этого, и в конце концов вы увидите свет в конце туннеля.
rebase
пониманием