Pull to refresh

Работа с Git без использования локальных веток

Reading time 4 min
Views 11K
Прочитав очередную статью про Git, я просто не мог не описать свой подход к решению вопроса, не претендующий на особую оригинальность. Я уже последний год успешно пользуюсь гитом, создавая минимум локальных веток. Не буду настаивать на том, что так делать правильно или неправильно — просто делюсь опытом. А для всех, кому интересно «как» — прошу под кат.

Disclaimer


Я не пытался избавляться и переводить на русский такие устоявшиеся в нашем кругу слова, как «закоммитить», «staged» файлы, форк, pull request (разве читает кто-то git man на русском?).

Я знаю, что Git может использоваться без центрального сервера, но в моём случае (и чаще всего) в проектах имеется что-то из GitHub, BitBucket или их аналогов.

Вероятно, эта статья не ориентирована на знакомящихся с Git. Скорее я в авторе упомянутой статьи узнал себя: однажды мне надоела куча локальных веток, лежащая в моей копии. А в тот момент у меня уже было хорошее понимание нюансов команд Git, и я решил рискнуть попробовать работать без локальных веток. Опыт оказался удачным — и я хочу им поделиться.

Начнём с вопроса: «какие функции выполняет локальная ветка?»


Она чаще всего лишь отслеживает удалённый аналог (с таким же именем или нет — не важно), постоянно с ним синхронизируясь. Легко перенести локальные изменения поверх того, что есть в удалённом аналоге, набрав git pull [--rebase]. Но у вас ведь могут быть еще незакоммиченные изменения (как в index/stage, так и not staged файлы).

Вам надо:

  1. сохранить неотправленные на сервер коммиты
  2. сохранить незакоммиченные файлы, возможно отделив staged от not staged, возможно, даже разбив эти файлы на 3-5 разных версий изменений.

Как результат, мы обычно используем git stash, создаём новые локальные ветки, что снова увеличивает их количество.
Наша оригинальная ветка осталась привязана к удалённой, но новосозданные ветки потеряли это преимущество — и всё равно приходится учить расширенный синтаксис команды git push. Как часто мы делаем git push не HEAD состояния (кроме случаев с тегами и удалением удалённой remote ветки)?

А что ещё полезного несёт локальная ветка в отличии от локального коммита? А у кого была при наборе команды git pull ошибка «There is no tracking information for the current branch»? Каждый раз приходится вспоминать команду привязывания локальной ветки к удалённой. А если мою локальную ветку надо связать с двумя репозиториями? А еще при git merge b надо помнить, совпадает ли у тебя b с origin/b — не лучше ли сразу делать git merge origin/b?

«Но у меня есть ветки, не привязанные к удалённым!»


Тут надо чётко понимать ответы на следующие вопросы:

  1. Когда я в последний раз работал с этой веткой?
  2. Когда она будет отправлена в удалённый репозиторий (или замерджена в одну из веток, которая попадёт в репозиторий)?
  3. Почему эта ветка сейчас не отправлена в репозиторий?


Я работаю над несколькими проектами. Но в каждом проекте над одной задачей одновременно. Потому HEAD у меня чаще всего находится в состоянии той самой задачи. И только в случае откладывания задачи «на потом» я создаю локальную ветку, не отправляя её на сервер. Почему не git stash? Stash легко потерять, очистив. Поскольку «переключения задач» происходят нечасто, приходится вспоминать синтаксис git stash, чтоб добавить осмысленное описание проделанных изменений (а не название коммита, на котором сделан stash). Не проще ли просто занести изменения в коммит, синтаксис которого я использую десятки раз за день — с указанием не только описания, но и даты? Когда эти ветки попадают в общий список локальных веток, становится еще опаснее чистить список локальных веток. Тогда я для себя решил, что все ветки, отправленные в репозиторий, я не хочу видеть у себя локально в git branch — я всегда могу сделать git checkout origin/b вместо git checkout b.

Представим, что вы заболели или уехали в отпуск или по любым другим причинам не выйдете на работу — где кому-нибудь взять то, над чем вы работали (ваши неотправленные локальные ветки)? Именно поэтому я предпочитаю их иметь как можно меньше.

Что если?


Из вышеописанного рецепт напрашивается простой: «закоммитил? проверил? — запушь!»

«Но что, если не успеваешь проверить?»
Если вы внезапно заболеете, а ваши наработки могут понадобиться кому-нибудь, лучше всё равно сделать git push. В зависимости от важности стабильности ветки, изменения можно отправить в ветку с другим именем.

Если эти изменения никому не понадобятся, и мне не захочется ночью из дома поработать над этими изменениями, только в этом случае я оставляю изменения без git push.

Ну и последний вариант: «еще не закоммитил». Тогда задача, на которую я переключаюсь, скорее всего очень важная, не терпящая отложения. А это означает, что скоро я вернусь к текущему состоянию: создаю ветку, коммичу изменения. Когда возвращаюсь, легко нахожу нужную ветку (у меня ведь их мало) — и продолжаю разработку, удалив ветку.

И что с того, что git status показывает «Not currently on any branch»? Правильное использование git log восполнит недостающие моменты. А так — процедура остаётся той же самой: git add, git commit. Только меняется git push origin HEAD:b (надеюсь, все пользуют уже git-autocomplete, помогающий быстро набирать имена веток?)

А что, если git push regected? Как обойтись без git pull [--rebase]? Я давно не пользуюсь git pull — не хочу помнить синтаксис еще одной команды: мне проще делать git fetch origin и, в зависимости от ситуации, либо git merge, либо git rebase, либо просто git checkout origin/b (если нет локальных коммитов). Особенно такой подход мне помогал контролировать каждый шаг в случаях, когда у меня было несколько удалённых репозиториев — и их приходилось между собой «переплетать» (какая версия лежит в releases/b понятнее, чем версия в ветке b).

Жизнь веток после пуша


Тут уже всё зависит от workflow в вашей команде. Чаще всего сервер репозитория синхронизирован с системой трекинга задач (например, JIRA). Такие системы как BitBucket имеют настройку удалять ветки после мерджа pull request, основанного на данной ветке. В общем, на remote репозитории всё живёт уже по настроенным правилам (главное иногда делать git remote prune origin), и не влияет на мою работу с Git. Тем не менее, уметь мерджить pull request из консоли тоже никогда не помешает!

Вместо послесловия


Всё, что у вас лежит локально — это ваше личное. Никому не интересно, сколько у вас локальных веток в репозитории — ваша team видит только то, что вы «запушили» (если, конечно, ваша локальная версия проекта не является удалённым репозиторием для других). А поэтому, организуйте работу с локальными сущностями Git, как вам удобно — ни у кого нет морального права судить вас за это до тех пор, пока «запушенный» результат вашей работы всех устраивает.

Мой результат устраивает мою команду уже на протяжении года.
Tags:
Hubs:
-2
Comments 15
Comments Comments 15

Articles