Github

Гитхаб — это платформа «социального кодинга»: удобное место для совместной работы над open-source проектами, в котором упор сделан на лёгкость правок и дополнений, а самое главное — клонирования чужих репозиториев, создание форков. К примеру, вы видите хороший репозиторий, в котором работают над каким-то интересным вам проектом. Однако, вам от этого проекта нужна только часть, или вы хотите на базе уже созданных функций сделать свои собственные — короче, хотите скопировать этот репо и продолжить работу над ним, не портя основной репо. Тогда вы делаете форк, клонируете его себе на компьютер и дальше работаете с ним — создаёте изменения, отправляете на сервер, но уже в рамках своего репозитория.

На гитхабе очень удобно редактировать код, а также смотреть старые версии проекта.

Коммиты

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

Каждый коммит необходимо сопровождать комментарием, описывающим проделанные изменения: из этого автоматически следует, что коммит — это некая завершённая маленькая часть работы. Не имеет смысла коммитить каждое изменение, к примеру простое объявление новой переменной — хотя некоторые так делают, и это называется атомарными коммитами. При таких коммитах история изменений быстро растёт, и становится проблематично быстро искать нужный этап при необходимости отката назад.

Теги

Более крупные этапы работы, т.е. законченные версии проекта, нужно помечать тегом. Самое логичное название для тега — номер версии. Теги удобны своей чёткой структурой (если придерживаться этой структуры!) и возможностью быстро посмотреть код любой версии проекта.

Кстати, я советую использовать версионирование в стиле SemVer: версия = мажор.минор.патч.

  1. Мажорная версия меняется редко, каждый раз когда вы ломаете API — т.е. форматы функций, структуры данных
  2. Минорная версия меняется чаще, каждый раз когда вы добавляете новые функции, не ломая совместимость
  3. Номер патча увеличивается при каждом изменении — то есть, при каждом коммите или чуть реже.

Бранчи

Очень, очень часто бывает такое, что ваши правки влекут за собой масштабные изменения — это добавление каких-то новых функций с необходимостью переделки большого количества кода, структур данных, других зависимых функций — или даже банальный рефакторинг. Делать это в рамках текущей копии кода проекта очень опасно — можно нечаянно всё сломать, хотя можно откатиться к старому коммиту. Чаще возникает ситуация такая (особенно на работе): собрался рефакторить, всё красиво разложил, развесил функции по верёвочкам, всё перед глазами — красота, можно начинать рефакторинг. И тут прибегают люди, кричат: «в прошивке глюки, срочно надо всё ремонтировать!». И что делать? Всё разложенное не соберёшь обратно быстро, откатываться на старый коммит жалко — столько работы пропадёт, по-старинке копировать код в отдельную папочку как-то глупо — зачем мы тогда Git используем?

Тут на помощь приходят бранчи, т.е. ветки. Перед началом масштабной работы, изменений которые ломают всю совместимость — делаете ответвление от основного дерева проекта. Создаётся копия текущего состояния проекта, так назваемый бранч — теперь можно вести работу в нём. Любые изменения в бранче не влияют на основную ветку, и когда приходится срочно возвращаться к основной ветке — это делается просто командой переключения. Подправив проект в основной ветке и закоммитив изменения, переключаетесь обратно и продолжаете ваять нетленку в боковой ветке.

Закончив рефакторинг или что-то ещё что вы делали в бранче — необходимо влить его обратно в основную ветку. Это несложная, но довольно муторная задача — нужно вручную отследить все изменения, произошедшие за это время в основной ветке, и добавить их в эту дополнительную. Если же изменений не было — просто заменяем старые файлы на новые из бранча.

Слияние

Если над кодом работает несколько человек, один и тот же файл может быть изменён одновременно всеми этими программистами — один добавил фичу А, другой — фичу Б, а на сервере вообще лежит старая версия без этих фич — ни у кого нет полной версии с обоими фичами. Как быть в такой ситуации? Нужно «слить» все изменения. Рассмотрим по очереди.

  1. На сервере лежит нулевая версия кода, два программиста скачали её себе (в свой локальный репозиторий) и вносят правки.
  2. Первый прогер написал фичу А, делает коммит/пуш, заменяет старую версию на сервере на новую версию кода с фичей А.
  3. Второй прогер добавил фичу Б, пытается её закоммитить — но сервер не даёт этого сделать, потому что видит несовпадение версий.
  4. Теперь второй прогер должен апдейтить свой локальный репозиторий, забрать с сервера изменённый файл — но теперь будет ругаться уже клиент git на его компьютере, потому что видит что старый файл был изменён прогером и не даёт затереть эти изменения.
  5. Второй прогер должен запустить мёржилку — в ручном режиме найти изменения первого прогера (фичу А) и добавить их в свой код с уже написанной фичей Б. К счастью, процесс этот довольно прост благодаря функции diff, которая подсвечивает все изменения. Это называется «слияние» или «сливание».
  6. Добавив все изменения, он подтверждает апдейт, и получает у себя самую свежую полную версию с обоими фичами. Теперь он делает апдейт, на сервер уезжает эта полная версия.
  7. Первый прогер делает апдейт у себя, получает полную версию. Обе фичи теперь разъехались по всем репозиториям, серверному и двум локальным.

Всё это — несложный, хотя иногда и довольно муторный процесс, но он даёт возможность работать над одним кодом совместно, увеличивая эффективность. Самое главное — апдейтиться как можно чаще, не оставляя процесс на самотёк: иначе вы будете работать с довольно старой версией кода, а при апдейте вам придётся, возможно, просидеть не один час над ручным слиянием очень разного кода.

И самое главное — не коммитьте плохой код, особенно ломающий нормальную сборку проекта. В больших компаниях человека, сломавшего билд, подвергают общественному порицанию :)