1 Вступление
В топике освещаются не столько подробности работы с git, сколько его отличия от схемы разработки других систем контроля версий, и общий подход (выработанный по большей части личным опытом и Git Community Book) к работе.
Современная разработка программного обеспечения стала чем-то большим, чем просто набором исходного кода программы в текстовом редакторе; она обросла целым комплексом дополнительного инструментария, вроде багтреккеров, систем для управления проектами и систем контроля версий (СКВ). Последние, пожалуй, играют особенную роль в проекте, поскольку определяют сам ход работ (или workflow).
2 Централизованные системы контроля версий
Классическим примером подобных программ в мире открытого софта являются CVS и ее потомок — Subversion (лозунг проекта — «CVS the right way»); проприетарные аналоги: Perforce или Clearcase. Эти системы строятся вокруг централизованной модели разработки, в которой существует единственный удаленный репозитарий, в который вносят изменения все разработчики проекта. Ветвление (branching) проекта возможно, но не желательно и приносит, как правило, только дополнительные сложности в проект.
Стандартный ход разработки выглядит примерно следующим образом: выкачивание из репозитария последней версии; разработка новой функциональности или исправление ошибок; повторное обращение к репозитарию для разрешения возможных конфликтов с работой других разработчиков; закачивание очередной ревизии на сервер.
Соответствующие команды: svn checkout (забрать последнюю версию), svn resolve (показать, что конфликт в исходном коде разрешен) и svn commit (создать в репозитарии очередную ревизию).
Подобный линейный подход к разработке прост и очевиден, но здорово ограничивает программиста. А что, если на любой из стадий цикла требуется отвлечься на другой функционал? Или срочно исправить какой-либо баг в предыдущей работе?
Существуют разные выходы из ситуации. Можно проявить твердость, и закончить текущую работу, чтобы потом обратиться к следующим этапам; или, как вариант, нагружать текущий коммит большим количеством изменений.
В первом случае не обеспечивается достаточная гибкость; во втором — усложняется поиск ошибки в коммите, нарушается логическая цельность действия.
Откатиться к начальному состоянию невозможно — значит потерять уже проведенную работу. Ну или, если совсем усложнить, завести отдельную копию проекта, в ней исправить ошибку (внести функционал), закоммитить, затем стереть копию, и вернуться к прежней работе… Сложно? Сложно. Не выход, иными словам.
Кроме того, иногда требуется работать без доступа к центральному репозитарию (удаленная работа, поездка и т.д. и т.п.). Что делать? Лишаться всякой гибкости разработки и заливать монстроидальный коммит весом в неделю?
3 Распределенный подход
Решением подобных проблем явилась альтернативная схема разработки, предлагаемая так называемыми распределенными системами контроля версий (Distributed Version Control System).
Среди открытых разработок на данную тему можно вспомнить git, Mercurial и Bazaar. Первый проект особенно интересен, он используется в некоторых из сложнейших современных программных систем(Linux Kernel, Qt, Wine, Gnome, Samba и многие другие), крайне быстро работает с любым объемом кода и сейчас набирает популярность в открытом мире. Какое-то время на распространении этой программы негативно сказывался недостаток документации; но сейчас этот недостаток можно считать устраненным.
Итак, в чем заключается глобальное отличие git (и DVCS вообще) от централизованных аналогов?
Во-первых, как следует из самого названия, не существует главного (в том смысле, который его понимают разработчики, привыкшие к SVN) репозитария. У каждого разработчика имеется собственный полноценный репозитарий, с которым и ведется работа; периодически проводится синхронизация работы с (чисто условно!) центральным репозитарием.
Во вторых, операции ветвления и слияния веток (merging) ставятся во главу угла при работе программиста, и поэтому они очень легковесны.
Кстати говоря, привычных ревизий также не существует; но об этом — чуть позже.
4 workflow в одну морду
Итак, рассмотрим простейший случай: личный проект, в котором участвует единственное одно лицо — вы.
Для создания нового репозитария достаточно просто зайти в папку проекта и набрать:
git init
Был создан пустой репозитарий — папка .git в корне проекта, в которой и будет собираться вся информация о дальнейшей работе (и никаких некрасивых .svn, разбросанных по дереву проекта!). Предположим, уже существует несколько файлов, и их требуется проиндексировать командой git add:
git add .
Внесем изменения в репозитарий:
git commit -m "Первоначальный коммит"
Готово! Имеется готовый репозитарий с единственной веткой. Допустим, потребовалось разработать какой-то новый функционал. Для этого создадим новую ветку:
git branch new-feature
И переключимся на нее (обратите внимание на отличие в терминологии по сравнению с SVN):
git checkout new-feature
Вносим необходимые изменения, после чего смотрим на них, индексируем и коммитимся:
git status
git add .
git commit -m "new feature added"
Теперь у нас есть две ветки, одна из которых (master) является условно (технически же ничем не отличается) основной. Переключаемся на нее и включаем изменения:
git checkout master
git merge new-feature
Легко и быстро, не находите? Веток может быть неограниченное количество, из них можно создавать патчи, определять diff с любым из совершенных коммитов.
Теперь предположим, что во время работы выясняется: нашелся небольшой баг, требующий срочного внимания. Есть два варианта действий в таком случае. Первый состоит из создания новой ветки, переключения в нее, слияния с основой… Второй — команда git stash. Она сохраняет все изменения по сравнению с последним коммитом во временной ветке и сбрасывает состояние кода до исходного:
git stash
Исправляем баг и накладываем поверх произведенные до того действия (проводим слияние с веткой stash):
git stash apply
Вот и все. Очень удобно. На самом деле таких «заначек» (stash) может быть сколько угодно; они просто нумеруются.
При такой работе появляется необычная гибкость; но среди всех этих веточек теряется понятие ревизии, характерное для линейных моделей разработки. Вместо этого каждый из коммитов (строго говоря, каждый из объектов в репозитарии) однозначно определяется хэшем. Естественно, это несколько неудобно для восприятия, поэтому разумно использовать механизм тэгов для того, чтобы выделять ключевые коммиты: git tag просто именует последний коммит; git tag -a также дает имя коммиту, и добавляет возможность оставить какие-либо комментарии (аннотацию). По этим тегам можно будет в дальнейшем обращаться к истории разработки.
Плюсы такой системы очевидны! Вы получаете возможность колдовать с кодом как душе угодно, а не как диктует система контроля версий: разрабатывать параллельно несколько «фишек» в собственных веточках, исправлять баги, чтобы затем все это дело сливать в единую кашу главной ветки. Замечательно быстро создаются, удаляются или копируются куда угодно папочки .git с репозитарием, не в пример SVN.
Гораздо удобней такую легковесную систему использовать для хранения версий документов, файлов настроек и т.д, и т.п. К примеру, настройки и плагины для Емакса я храню в директории ~/site-lisp, и держу в том же месте репозитарий; и у меня есть две ветки: work и home; иногда бывает удобно похожим образом управлять настройками в /etc. Естественно, что каждый из моих личных проектов тоже находит под управлением git.
5 Общественные репозитарии
Общественный репозитарий — способ обмениваться кодом в проектах, где участвует больше двух человек. Лично я использую сайт github.com, настолько удобный, что многие начинают из-за него пользоваться git.
Итак, создаем у себя копию удаленного репозитария:
git clone git://github.com/username/project.git master
Команда создала у вас репозитарий, и внесла туда копию ветки master проекта project. Теперь можно начинать работу. Создадим новую ветку, внесем в нее изменения, закоммитимся:
git branch new-feature
edit README
git add .
git commit -m "Added a super feature"
Перейдем в основную ветку, заберем последние изменения в проекте, и попробуем добавить новую фишку в проект:
git checkout master
git pull
git merge new-feature
Если не было неразрешенных конфликтов, то коммит слияния готов.
Команда git pull использует так называемую удаленную ветку (remote branch), создаваемую при клонировании удаленного репозитария. Из нее она извлекает последние изменения и проводит слияние с активной веткой.
Теперь остается только занести изменения в центральный (условно) репозитарий:
git push
Нельзя не оценить всю гибкость, предоставляемую таким средством. Можно вести несколько веток, отсылать только определенную, жонглировать коммитами как угодно.
В принципе, никто не мешает разработать альтернативную модель разработки. Например, использовать иерархическую систему репозитариев, когда «младшие» разработчики делают коммиты в промежуточные репозитарии, где те проходят проверку у «старших» программистов и только потом попадают в главную ветку центрального репозитария проекта.
При работе в парах возможно использовать симметричную схему работы. Каждый разработчик ведет по два репозитария: рабочий и общественный. Первый используется в работе непосредственно, второй же, доступный извне, только для обмена уже законченным кодом.
6 Заключение
Я старался не акцентировать внимание на всех тонкостях использования главных команд, тем более что почти наверняка не знаю их все, да активно использовать git начал сравнительно недавно; но хотел продемонстрировать именно простоту и гибкость этого замечательного средства разработки. Также не стремился объяснить особенности внутренней механики проекта; хотя бы даже потому, что изящность и красота реализации заслуживает как минимум еще одного хабратопика.
Естественно, приветствуются указания на фактические ошибки, подсказки насчет использования системы и общие замечания. :)
UPD: разжился кармой и перенес в блог Git
UPD2:
продолжение заметки, несколько неформатное для Хабра :)
комментарии (136)
Хотя в своём интервью Линус Торвальдс говорил, что SVN продолжает отлично работать в большинстве проектов, но Git хорош в больших и сильно распределённых проектах.
Так что надо пробовать, и самому делать выводы.
Svn выглядит довольно неуклюже даже в маленьких проектах. Его папочки раскиданы по всему дереву проекта, репозитарий создается сравнительно долго, хранится отдельно…
А в git создание репозитария в проекте выглядит так:
cd project
git init
git commit -a -m «initial commit»
Easy pie, не находите?
Да и в SVN существенно медленее выполняются и сами операции.
Коммит в основной репозитарий после каждого пука — это палка о двух концах. с одной стороны ничего не потеряется, с другой — в репозитарии много фигни нерабочей.
Если придерживаться правила — «рабочий код» в репозитарии, то абы какой код коммитить не будешь. При этом конечно возрастет вероятность потерять похерить сделанную работу.
Если репозитарий в локальной сетке, то commit выполняется относительно быстро. Update — дольше. Но лично для меня время коммита/апдейта не настолько критично чтобы менять СКВ.
Вот если разработчики разбросаны по миру, то тут наверное git будет удобнее. Да. Возможно удобнее делать патчи.
Скажите, если вы с git работали — там конвертатор есть какой-нибудь. svn -> git, cvs -> git и обратный?
cvs -> git — напрямую нет, советуют сделать cvs -> svn -> git :)
но опять получается что все это зависит от того как устроена работа.
я смотрю редко, для того чтобы узнать что я закоммитил в предыдущие разы. вы смотрите каждый раз для того чтобы что-то ненужное не ушло в общественный репозитарий.
Вот-вот, организуется полнейший бардак. Сколько ни думал над революционностью Git, так и не понял ее. Линус, вобщем-то, так и говорит, что ничего нового, просто нет централизованного хранилища и действительно бенефиты только при сильно распределенных проектах.
Однако, как бы разработчики не колдовали, сколько бы сотен собственных бранчей не имели, чаще всего на выходе будет одна единственная ветка продукта, которая продается или передается заказчику. Иногда таких веток две или три, в случае поддержки нескольких версий продукта.
Короче говоря, в любом случае требуется линеаризация изменений в общий бранч, мердж и т.п., и наличие при этом сотни веток на каждого разработчика совершенно выглядит излишним: какую брать? в какой все нужные исправления? много вопросов.
Не спешите уходить с централизованных репозиториев.
Чаще всего есть две-три ветки. Одна из них это master и HEAD в ней — последний коммит, извлеченный с центрального репозитария. Плюс одна веточка на новую фишка. Заканчиваешь работу с ней — сливаешь в основную. Коммиты в результате становятся мельче и точнее. Можно, к примеру, вытаскивать отдельные подкоммиты в дочерней ветке и вливать в master.
Не надо путать ветки в svn и ветки в git. В первом ветка — это тяжелое изменение, накапливающее множество изменений. Естественно, что ее трудно слить в главную. В git ветка, это скорее веточка, включающая буквально два, три, редко пять коммитов.
Обычно в центральном репозитарии вообще хранится одна ветка, а ля subversion, которая и будет на выходе проекта. Тут действительно не стоит разводить сложных деревье; более того, сознательно поддерживается простая линейная история разработки.
«Не надо путать ветки в svn и ветки в git» — никто же не запрещает делать ветки в svn такими же короткими как в git, пусть у вас хоть на каждую фичу будет своя ветка, а потом сливайте нужные ветки (фичи) в один бран, если они действительно независимы, то мерджа не будет.
Главное хранилище в результате выглядит похожим на обычный svn; разработчики же на местах получают всю необходимую гибкость.
Что такое «главный репозитарий» я не очень понимаю, с точки зрения svn репозитариев может быть несколько, а в каждом репозитарии ветвиться можно по каталогам.
Опять же, ни разу не встречал схемы с несколькими репозитариями.
Что-то не помню, чтобы наш тимлид вообще кому-либо позволял разводить такой бордель в центральном репозитарии :) Это ж форменное безобразие!
Не копирует.
Если это частная ветка, то какая разница, в общем она репозитории или в частном?
Это, как уже обсуждалось, зависит от политики коммитов.
Вот работа оффлайн — это пожалуй единственный весомый аргумент, из приведенных вами.
Неспешите уходить с централизованных репозиториев.А вообще пахнет религиозностью :)
Судя по всему не только. Есть даже TortioseGit.
> Есть плагины для всех IDE
Меня устраивает Tortoise*, а она есть и для Mercurial, и для Git.
> Вообще реально для небольших корпоративных проектов я не видел причины почему не справится обчный svn.
Пока хочу просто попробовать. Правда, возможность избавиться от назойливах папок .svn тоже привлекает :)
Скачать можно здесь — code.google.com/p/nbgit/
(Для Eclipse тоже есть — code.google.com/p/egit/ )
p.s. git есть уже и под win и под mac os x. и GUI есть тоже кросплатформенный. (qgit например)
Однажды мне пришлось работать неделю без доступа к центральному репозитарию. Накопилось множество изменений, и в результате целый день по возвращению в офис пришлось решать конфликты, чтобы совершить коммит. Кроме того, смущала невозможность фиксировать отдельные части изменений.
В git это выглядело бы чуть проще. На каждую из разрабатываемых фишек я бы создавал отдельную ветку; и потом, с появлением доступа к Инету, или возвращением в офис, каждая из новых возможностей аккуратно заливалась в обновленный master с постепенным разрешением возникающих конфликтов.
* Для каждой фичи делаем ветку, но по ее завершению в свой master не коммитим
* Когда получаем доступ к
телуглавному репозиторию, обновляем свой master* В свой master коммитим все изменения главного мастера и заодно правим конфликты.
* Коммитим свой master в master главного репозитория.
Есть еще такая команда git rebase, которая позволяет поддерживать линейность главной ветки центрального репозитария. Я о ней не писал специально, чтобы не пудрить мозги лишней информацией.
Строго говоря, ничего страшного в git rebase нет, это просто такой способ «бесшовного» объединения вашу и других разработчиков работу, когда изменения проводились параллельно.
* Делаем ветку, в ней работаем и делаем мелкие коммиты — не длинее дня.
* Регулярно обновляем свой мастер с главного репозитария
* Делаем слияние с обновленного мастера — в ветку с фичей, то есть подтягиваем общий код фичи до текущего состояния.
* Когда решили что фичу надо зарелизить — делаем обратное слияние в мастер и главный репозитарий.
При таком подходе — конфликтов на релизе почти не бывает =)
ЗЫ. А можно ветку и не релизить в мастер — по этому принципу форки опенсоурсных проектов работают.
Причем делать это можно как через git merge, так и через git rebase.
Последний — это вообще шикарная фича, но пользоваться её надо с умом и осторожно.
В своем локальном репозитарии вы проводите основную работу с коммитами, ветками и т.д. и т.п. При такой легкости создания веточек резонно делать коммиты маленькими, слияния с ветками — регулярными, даже частыми.
Мой опыт показывает, что конфликты возникает примерно с той же регулярности, что в Svn, ничего особенного.
Аналогичное проще: git checkout -b new-feature
В общем, видимо надо ещё одну статью, а то по git не было ничего, а лично мне интересно очень, ибо svn слегка напрягает.
www-cs-students.stanford.edu/~blynn/gitmagic/index.html
В Windows да, WinMerge, в Ubuntu юзаю Meld (по-моему, стандарт). По крайней мере, он настолько удобнее всего остального, что меня устраивает на 110%.
Но если в двух словах…
При неудачной попытке слияния в конфликтных местах в индексе помечаются проблемные файлы; внутри же самих файлов расставляются метки, похожие на Svn-овские. После разрешения этих вопросов надо проиндексировать эти самые исправленные файлы — и совершать коммит. Если какой-то из «карявых» файлов не был исправлен — коммит совершен не будет.
Выглядит это так:
git merge conflicting-branch
>>>>> здесь тебя оповещают о конфликтах
edit TROUBLED_FILE
git add TROUBLED_FILE
git commit -m «resolved a conflict»
Ну вот и все, конфликт решен, никаких новых комманд.
Остаётся вопрос об откатах или переключениях на другие версии :-)
Вообще, конечно, было бы отлично видеть это всё в виде статьи — эту я в избранное добавил, вот вторую туда же бы — и вуаля, миниучебник по гит в кармане :-) Мечта!
git reset ВЕРСИЯ --hard
Откат к предпоследней версии в репозитарии:
get reset HEAD^ --hard
Можно писать HEAD^^ и т. д., можно указать примерное время коммита, а можно просто SHA1-номер версии (или первые несколько его букв, чтобы они были уникальны).
Команды выше применяют изменения только на репозитарий, файлы в рабочей папке изменяются отдельными командами:
git reset ВЕРСИЯ
и т. д.
Например, если вы программировали-программировали и поняли что фигня получается, то откатить все изменения в рабочей папке:
git reset HEAD
git commit --amend
репозиторий svn представляет собой, по сути дела, набор снимков состояний дерева каталогов. и ветки там — просто каталоги, а мердж — наложение снимков состояний одного каталога на другой каталог. хранением истории слияний приходится заниматься или в уме (до svn 1.5) или в метаданных (после), иначе возможно повторное применение изменений, чем собственно и неприятны слияния в svn.
в DVCS репозиторий — ациклический направленный граф (DAG) состояний одного и того же каталога, поэтому при мердже приходится объединять два состояния каталога в одно (в hg это максимум, в git у ревизии может быть множество родителей), что может быть проведено автоматически, а конфликты разрешаются вручную с помощью внешних утилит. потом осуществляется коммит и мы вместо двух веток получаем одну. в результате история слияний гораздо нагляднее.
Не так давно вычитал про новый ключ команды git log, он выведет ASCII-репрезентацию истории коммитов. Лично, однако, не видел — у меня до сих пор живет Ubuntu 8.04, обновляться же пока на работе и дома использую один ноутбук слишком рисково. Но скриншоты выглядят довольно мило :)
Вызывать так:
git log --graph
И в качестве комментария, хочу отметить, что Git на моей машине с удалённым репозиторием unfuddle связывается и делает push/pull быстрее (в несколько раз!) чем svn с сервером, находящимся в соседней комнате. Масштабы проектов примерно одинаковы.
А говорят, что Mercurial ещё быстрее :)
Меня скорость Git-а устраивает, а как известно, от добра добра не ищут :)
если слияние будет проходить быстрее чем сейчас, не 1,5 секунды, а 0,9 секунды. Я прям не знаю, куда я буду использовать эти освободившиеся за день 10*0,6=6 секунд… :)))))
А можно поподробнее в чем именно
mercurial для негиков — консольные команды похожи на svn, основная функциональность постигается за два часа, более продвинутые возможности — за счет расширений (bookmarks, convert, rebase, shelve и тд)
кривая обучения вполне себе обычная для таких систем: показал несколько команд, объяснил как пользоваться, подсказал, где доки хорошие лежал. Вот и все. Как документация нормальная появилась — сразу налет таинственности слетел.
Это все больше очередная айтишная легенда, вроде стиля такого.
Поясню. У меня в проекте в svn используется следующая практика.
Есть основной репозиторий (транк). При необходимости сделать какие-то изменения, девелопер открывает таск-бранч (копирует транк через svn copy). После делает изменения в таск-бранче и коммитит туда. Соответственно потом тимлид может взять этот бранч из общего репозитория, проверить изменения и смержить в общий транк. То есть это практика проверки девелоперского кода и безопасности основного репозитория от случайных коммитах.
Есть ли какая-нибудь аналогичная схема для git/mercurial/etc.?
При использовании отдельного репозитория в качестве центрального, любой разработчик может «опубликовать» на нём свой локальный бранч и таким образом организовать совместную работу.
Из статьи видно что создаётся бранч локально, и локально же потом мержится в мастер-репозиторий. А как этот же бранч сделать доступным всем?
В комментах, как посмотрю, накопилось довольно много конкретных вопросов по командам; а статья задумывалась как чисто обзорная. Я постараюсь эти и многие другие вопросы подробно осветить в следующем топике на ту же тему.
Время терпит? :)
Локальный бранч и удаленный бранч — это всё же разные бранчи, даже если локальный бранч следит (tracking) за удаленным и они имеют одинаковые имена (хотя имена тут не имеют вообще никакой роли).
Есть одно неплохое руководство по гиту — Git Guide.
На основе его могу привести пару примеров работы с удаленными бранчами.
Итак, вначале создаем локальный бранч с именем foobar и переходим в него:
Дальше можно сразу же опубликовать его, а можно вначале закоммитить в него что-то — смотря как вам удобнее. В любом случае, когда решите публиковать его на сервере по умолчанию (origin), выполняете такую команду:
После этого другой разработчик может создать у себя локальный бранч, которые будут следить за удаленным бранчем, который вы создали, таким образом:
Я опустил пару полезных моментов, в которые стоило бы углубиться, но в целом этого вполне достаточно для работы с удаленными бранчами.
git push origin foobar:refs/heads/foobar
использовать
git push origin foobar:foobar
? Это ведь будет работать, или нет?
Мне сейчас неудобно экспериментировать, под рукой только корпоративный сервер.
Кроме того, в файле по адресу your-project/.git/info/allowed-users возможно оставлять совсем точные указания по управлению доступом к веткам, созданию тегов и прочему. Пример содержимого файла с первого попавшегося howto:
refs/heads/master alice\|cindy
refs/heads/doc-update bob
refs/tags/v[0-9]* david
Первая строка показывает, что alice и cindy могут коммититься в главную ветку (женщины), bob — в doc-update; а david, как технический менеджер, может заниматься заданием тегов-версий приложения.
иерархию репозитариев — сорри, что имеется в виду? иерархия по какому признаку?
Иерархия — система репозитариев. Например, есть четыре младших девелопера, два старших и архитектор.
Старшие получают по одному общественному репозитарию, в которых занимаются приемом работы младших. Принятые на этом уровне коммиты отправляются дальше, в общественных репозитарий архитектора, который решает, включать ли данную работу в production.
Конечно же, эти вещи можно автоматизировать (например, это делает GitHub), но простор для фантазии практически безграничен.
emerge -av git
…
* dev-util/git
Latest version available: 1.6.0.6
Latest version installed: [ Not Installed ]
Size of files: 2,725 kB
Homepage: git.or.cz/
Description: GIT — the stupid content tracker, the revision control system heavily used by the Linux kernel team
License: GPL-2
Клёво.
А по факту, я не совсем понял — как можно вернуться к какой-то определенной ревизии? Бывает, что программист либо в коде накосячил сильно либо удалил что-то нужное и необходимо вернуться назад на какое-то количество шагов. Подскажите, как быть?
Отдельные коммиты можно откатить командой «git reset».
Имейте в виду, что она не имеет ничего общего с командой «svn reset», кроме названия.
Этой же командой можно отменять целые мерджи, но делать это нужно осторожно, потому что… в общем, тут начинаются сложности.
Можно откатить и все коммиты до определенной версии, но только в том случае, если эти изменения ещё не покинули пределы вашего репозитория — для этого есть команда «git reset». Только с ней нужно быть ещё осторожнее — в умелых руках, она может уничтожать коммиты безвозвратно :)
Ветвелние к централизации-децентрализации никакого отношения не имеет. Все дело в удобстве работы с ветками в той или иной системе. В CVS это «ужас-ужас», в subversion немного получше, но проблемы с reflective/cyclic merges мешают жить хорошо. В Perforce же (уж на что централизованая и old school система, без доступа к репозиторию ничего не работает) ветки одно из основных понятий.
По-моему мнению, неправильно сводить выбор технологического инструментария для конфигурационного управления к удобству управления ветками. Есть требования инфраструктурные, есть процессные, есть секьюрные требования и т.д. Например, для CMM 3 необходима интеграция системы конфигурационного управления с системой управления изменениями (issue management, change management). Где-то требуется обязательный доступ через WEB, где-то высокие требования к ограничениям прав доступа к исходникам. А кто-то жить не может без интеграции со средой разработки. Не последнюю роль играют организационные факторы — наличие на рынке труда специалистов, знающих инструмент, а также наличие технической поддержки продукта в России.
Финансисты же — народ консервативный, даже в айтишной сфере; им проще судить о том, что было и сейчас в зените популярности; а том же, что только входит в мэйнстрим, они рассуждать не могут и не будут. Тут надо обращаться к аналитикам другого рода… Прежде всего надо спрашивать у самих разработчиков.
Svn сделала историю; более того, стала символом всех централизованных систем благодаря своей простоте и логичности. Естественно, что прежде чем икона сменится, пройдет минимум несколько лет.
читая статью, ожидал увидеть немного слов про софт. в итоге нашел немного упоминаний в комментариях.
еще ожидал упоминаний про интеграцию в основные среды разработки. конечно к workflow это не относится, но всё-таки является дополнительным аргументом к использованию git.
Eclipse: code.google.com/p/egit/
eigenclass.org/hiki/gibak-backup-system-introduction
из описания почему пришлось делать gibak:
The major thing missing in Git when used as a backup tool is support for file metadata (mostly file permissions) and empty directories (git just ignores them). git-home-history doesn't handle them at all, and etckeeper relies on metastore to preserve a snapshot of the metadata (owner, group, permissions, mtime, etc.) in a .metastore file located at the top of the git repository (/etc in the case of etckeeper).
Пока что не нашёл простого способа заставить системы контроля версий (и git в частности) работать в таком стиле, но мне кажется, что подобный стиль очевиден и многие должны с ним столкнуться. Как вы поступаете в таком случае?
Но это конфигурации, в них редко делаются правки. А если это центровой и очень популярный в проекте файл, в который довольно часто льются коммиты и в котором так удобно держать свой код, который, например, дапмит в файл только вам нужные данные?
Например,
git revert BAD_COMMIT_TAG
отменит какое-то из коммитов в истории, который вы пометили как плохой.
Использовать git revert обязательно в случае, если вы имеете дело, например, с общественной веткой, когда изменения уже попали во множество чужих локальных репозитариев.
Другой способ, если изменения не коснулись кого-либо кроме вас — команда git rebase, отвечающая за физические изменения в истории проекта. Пример:
git tag BAD_TAG work~5 — отмечаем проблемный коммит (пять коммитов назад по истории в ветке work) тэгом
git checkout BAD_TAG — переключаемся на этот коммит
… убираем ненужные вещи
git commit --amend — собственно, коммит модификации
git rebase --onto HEAD BAD_TAG work — накладываем последующие коммиты на внесенные изменения
Ну а в общем, в своей работе разве у вас нет какой-нибудь пятёрки коммитов, которые постоянно болтаются на вашем рабочем бранче и которые хочется всегда видеть у себя но никогда в основном репозитории? Или это только с моим стилем работы что-то не так?
Сложный путь — вроде того, что я описал одним моим сообщением выше, когда лезем в историю, физически ее меняем…
Путь, что мне больше по душе — сделать revert слияния:
git revert 81a94bb976dfaaaae42ae2600b7e9e88645ebd81 -m 1
здесь хэш определяет коммит слияния, ключ "-m 1" обозначает номер оставляемой ветки, обычно первый (ветка, в которую вливались).
— Разработчик1 в своем локальном бранче1 сделал некую правку1. Смержил бранч1 с бранчем master. Отправил master в центральный репозиторий.
— Разработчик2 в своем локальном бранче2 сделал некую правку2. Смержил бранч2 с бранчем master. Отправил master в центральный репозиторий.
Главный разработчик посмотрел обе правки и нашел, что правка1 — хорошая, а правка2 — плохая. Правку1 главный разработчик хочет теперь применить в рабочем проекте.
Вопрос — как главному разработчику обновить рабочий проект, так, чтобы в него попала только хорошая правка1, а плохая правка2 не попала?
Дело осложняется тем, что правка — это не один конкретный коммит, а несколько, в разнобой с другими коммитами.
Если ответ — не надо было допускать плохую правку в master, то тогда возникает другой вопрос — а как тогда вообще обмениваться правками?