Skip to content

Ru:PullRequest

stev edited this page Nov 4, 2011 · 15 revisions

О Pull Request'ах.

(эта статья недописана находится тут, а не в основной onPHP wiki, т.к. мне не хочется ее пихать в основную wiki недописанной). Если есть комментарии, предложения, пожелания по ней - пишите в личку :)

Статья состоит из 3-х частей:

  1. Общие правила заведения и рассмотрения Pull Request'ов.
  2. Описание-пример как создавать Pull Request и мержить его.
  3. Небольшой обзор git с точки зрения как его представляю "я" и как с ним работать :)

Описание-пример как создавать Pull Request и мержить его

Это описание workflow как работать с Pull Request'ами на github'е. В примере я буду использовать свой fork фреймворка: git@ github.com:AlexeyDsov/onphp-framework.git

  • Если еще не сделали, то делаем fork проекта. После этого у вас появляется свой репозиторий по адресу.
  • Выгружаем себе локально свой репозиторий, например так:
mkdir ~/onPHP-fork
cd ~/onPHP-fork
git clone [email protected]:AlexeyDsov/onphp-framework.git .

Теперь все последующие операции с репозиторием будем выполнять из папки ~/onPHP-fork

  • Подключаем основной onphp-framework репозиторий, например так:
git remote add onphp-origin [email protected]:onPHP/onphp-framework.git
git remote update
  • Если fork был сделан раньше и нужно догнать в своем бранче-мастере мастер из основного репозитория то пишем, например, так:
  • выполняет слияние локального мастера с мастером из главного репозитория
git merge onphp-origin/master
  • отправляем обновление своего мастера на свой fork (тот который у меня AlexeyDsov)
git push origin master:master
  • Теперь все готово что бы сделать бранч, например, myNewFeature в котором можно сделать feature:
git checkout -b myNewFeature
  • Выполняем нужные правки и после этого коммитим изменения в локальный репозиторий:
git add file1 file2 file3
git commit -m 'implemented new feature myNewFeature'
  • Когда сделаны все коммиты, то необходимо локальные изменения слить в свой форк. Таким образом там нужно тоже создать отдельную ветку под изменения:
git push origin myNewFeature:myNewFeature
  • После этого заходим на github в свой форк во вкладку Network и кликаем на последний свой коммит в ветке myNewFeature. В этом жмем вверху-справа кнопочку Pull Request и заполняем после этого тему реквеста и описание, жмем кнопку Send Pull Request. Вот собственно Pull Request и создался. Если вдруг хочется сделать какие-либо правки в ветке и добавить коммит, то просто делаем правки, коммитим их в ту же ветку и опять пишем git push origin myNewFeature:myNewFeature. А github в Pull Request'е сам подтянет новые коммиты в ветке.
  • Когда обсуждение успешно окончено и решено замержить Pull Request, то контрибьютер может нажать в реквесте кнопку Merge если merge не приводит к конфликтам. Если же merge приводит к конфликтам и невозможен в автоматическом режиме, то есть два способа решения:
  1. Можно замержить мастер в myNewFeature, решить конфликт и далее безконфликтно замержить myNewFeature в master.

  2. Можно просто замержить myNewFeature в мастер решив при этом конфликтю. Рассмотрю второй вариант. Пусть я контрибьютор и у меня под рукой нет выгруженного репозитория:

git clone [email protected]:AlexeyDsov/onphp-framework.git onPHP-fork

//создает репозиторий и подключает к нему remote репозитория AlexeyDsov с именеме origin

cd onPHP-fork
git remote add onphp-origin [email protected]:onPHP/onphp-framework.git 

// подключаем главный onphp репозиторий и называем его onphp-origin

git checkout -b onphp-master -t onphp-origin/master 

//создаем локально бранч onphp-master следящий за веткой master из репозитория onphp-origin. При этом сразу и переключаемся на этот новый бранч.

git merge origin/myNewFeature

//мержим из репозитория origin бранч myNewFeature и получаем конфликт //дальше решаем конфликт либо через mergetool либо совсем ручками и коммитим все незакоммиченные файлы //после этого push'им изменения в мастер главного репозитория:

git push onphp-origin onphp-master:master

Github этот мерж должен будет сам увидеть и автоматом закроет Pull Request под тем кто выполнял ручной merge.

Небольшой обзор git с точки зрения как его представляю "я" и как с ним работать :)

Здесь я отталкиваюсь от отличий с svn'ом и это скорее набор примечательных фактов которые я отмечаю(л) при работе с git'ом:

  • В отличие от svn каждая папка созданная с помощью git clone сама по себе является полноценным репозиторием со всей историей коммитов.
  • Для git в ubuntu есть хороший клиент просмотра дерева коммитов - sudo apt-get install gitg. И далее из корневой папки репозитория нужно его запустить: gitg&
  • По моим ощущениям бранчи можно называть "указателями ветку" коммитов. Таким образом если какой-то бранч удаляется, то сам коммит еще остается в репозитории.
  • Работа с внешними репозиториями это git remote. С помощью git remote add repositoryName repositoryUrl можно подключать новые репозитории, а дальше с помощью git remote update выкачивать обновления по ним полностью.
  • Для создания локального бранча связанного с бранчем удаленного репозитория нужно писать git checkout -b newBranch01 -t remoteRep/newBranch Где newBranch01 - имя бранча в локальном репозитории, remoteRep - имя удаленного репозитория, а newBranch - имя бранча в удаленном репозитории. если названия бранчей в локальном и удаленном репозитории будут совпадать, то достаточно будет git push для публикации изменений. С помощью настроек в конфиге опции push.default можно выбрать поведение, какие бранчи будут публиковаться (ни какие, все совпадающие по имени, отслеживаемые из удаленного репозитория, текущий)
  • git commit -m 'message' - коммитит в локальный репозиторий
  • git pull - это fetch + merge или fetch + rebase (если запускать с параметром --rebase). При этом, кажется, бранч должен быть связан с удаленным репозиторием через checkout -t
  • git push repositoryName myInternalBranch:remoteBranch - отправляет изменения локального бранча myInternalBranch в бранч remoteBranch удаленного репозитория repositoryName. При этом если тип обновления это не fast-forward, то удаленный репозиторий не позволяет выполнить свое обновление
  • fast-forward обновление - такой тип обновления когда к текущей ветке можно просто добавить новые коммиты и сдвинуть указатель бранча дальше по ветку
  • git push repositoryName :remoteBranch - удаляет в удаленном репозитории repositoryName бранч remoteBranch
  • git status часто подсказывает что нужно сделать с файлами что бы закоммитить/вернуть их состояние на дефолтное.
  • Когда нужно откатить какой-то коммит(ы) который(ые) был(и) сделан(ы) некоторое время назад, то можно написать: git diff идентификатор_нового_коммита идентификатор_старого_коммита > mydiff.diff && git apply mydiff.diff && rm mydiff.diff
  • Если нужно применить изменения одного из коммитов в другой ветке, но мерж/ребейз делать нельзя (например ветка master ушла вперед, а в 1.0 правятся только баги), то стоит использовать git cherry-pick идентификатор_коммита