Я использую 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
По существу, создайте ветвь признаков, ВСЕГДА переустановите от мастера к ветке и слейте из ветки обратно в master. Важно отметить, что ветвь всегда остается локальной.
Вот рабочий процесс, который я начал с
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, и они охватывают много слияния и едва упоминают о rebase.
Во всяком случае, я следил за своим рабочим процессом в недавнем филиале, и когда я попытался объединить его с хозяином, все это попало в ад. Было много конфликтов с вещами, которые не должны были иметь значения. Конфликты просто не имели для меня никакого смысла. Мне потребовался день, чтобы разобраться во всем, и в итоге завершился вынужденным толчком к удалённому мастеру, поскольку у моего локального хозяина все конфликты разрешены, но удаленный все еще не был счастлив.
Каков "правильный" рабочий процесс для чего-то подобного? 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
Фактически, наш рабочий процесс немного отличается, так как мы склонны делать сквош-слияния вместо сырых слияний. (Примечание. Это противоречиво, см. ниже.). Это позволяет нам превратить всю нашу ветку функций в единую фиксацию на сервере. Затем мы удалим нашу ветвь функции. Это позволяет нам логически структурировать наши фиксации на мастере, даже если они немного грязны в наших ветких. Итак, это то, что мы делаем:
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 (другие?) Pull Requests. Если вам интересно, как слияние/переустановка относится к Pull Requests, я рекомендую выполнить все вышеперечисленные шаги до тех пор, пока вы не будете готовы к объединению вернуться к мастеру. Вместо ручного слияния с Git вы просто принимаете PR. В частности, он работает следующим образом:
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. Если вы боретесь, просто придерживайтесь его, и в конце концов вы увидите свет в конце туннеля.