Экспресс-курс · No. 17

Git записывает каждую версию твоего проекта и позволяет целой команде менять одни файлы, не затирая друг друга. Почти весь страх вокруг него идёт от незнакомых слов — commit, branch, rebase, — а не от реальной сложности. Выучи горстку терминов, и Git из источника ужаса превратится в самую спокойную страховочную сеть, что у тебя будет.

Только суть · Один образ на идею · Выучи слова

§ 01

До команд — задача. Как только почувствуешь боль, что контроль версий убирает, каждая фича Git читается как очевидный ответ, а не как произвольный жаргон.

Папка, полная файлов _final_v2_FINAL

Стол, заваленный report.doc, report_v2.doc, report_final.doc, report_final_FINAL.doc — никто не уверен, какой текущий, а хорошая версия со вторника потеряна навсегда.

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

Git держит ленту снимков

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

Git — это система контроля версий, что использует почти каждый. Она записывает твой проект как серию снимков (snapshot) — каждый полная картина всех файлов в момент, что ты выбрал сохранить. Итог — лента, по которой можно путешествовать: смотреть, что изменилось, когда и кем, и вернуться к любому прошлому состоянию. Это кнопка сохранения, что не забывает ни одного сохранения.

Репозиторий — это проект плюс вся его история

Книга, что несёт каждый черновик, которым была, вплетённый в конец, — ты держишь текущий текст и полную запись того, как он таким стал, вместе.

Репозиторий (или репо) — это папка твоего проекта, когда Git его отслеживает: текущие файлы плюс вся скрытая история каждого когда-либо сделанного снимка. Клонируй репо — и получишь не только сегодняшний код, но всю историю. Это единица, в которой ты работаешь, — репо это «проект, что Git помнит», и всё остальное в курсе — это что-то, что ты делаешь внутри него.

Контроль версий заменяет папку копий _final_FINAL одним проектом и полной, восстановимой историей. Git держит эту историю как ленту снимков.

§ 02

Самое важное слово в Git — коммит, один сохранённый снимок в ленте. Пойми, как делается коммит, — и поймёшь сердцебиение всей системы.

Коммит — это один сохранённый снимок

Фотография всего твоего проекта в выбранный миг, подшитая с запиской о том, чем был этот момент, — приколотая навсегда к ленте.

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

Staging area: упакуй коробку до того, как запечатать

Коробка для отправки на столе: ты кладёшь в неё ровно те предметы для этой посылки, оставляя другие в стороне, и лишь потом заклеиваешь и шлёшь.

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

Сообщение — это записка будущему

Подписать ту запечатанную коробку тем, что внутри, — чтобы месяцы спустя кто-то, оглядывая полку, знал, что в каждой, не открывая.

Каждый коммит несёт сообщение коммита (commit message), объясняющее, что изменилось и почему. Кажется рутиной, а позже — чистое золото: когда ты охотишься за изменением, что что-то сломало, или понимаешь, почему строка существует, сообщения — это история проекта. Хорошее сообщение («fix timezone bug in invoice export») превращает историю из стены загадочных ID в читаемый лог. Пиши их для того, кто прочтёт через полгода, — обычно для себя.

HEAD — это твой маркер «ты здесь»

Точка «ты здесь» на карте ленты — она отмечает, на каком снимке ты сейчас стоишь.

HEAD — это указатель Git на то, где ты сейчас в истории, — обычно последний коммит на текущей линии работы. Когда ты делаешь новый коммит, он добавляется сразу после HEAD, и HEAD двигается вперёд к нему. Ты редко трогаешь HEAD напрямую, но слово появляется повсюду, и знать, что это просто «моя текущая позиция в ленте», демистифицирует бо́льшую часть того, что прочтёшь.

Коммит — это один сохранённый снимок. Ты добавляешь в индекс ровно те изменения, что вместе, потом запечатываешь их сообщением — а HEAD отмечает, где ты стоишь.

§ 03

Ветки — это где Git перестаёт быть навороченной кнопкой сохранения и становится способом для многих людей — или многих идей — двигаться разом, не наступая друг на друга.

Ветка — это параллельная линия работы

Ксерокопировать рукопись, чтобы черкать смелую переработку на своей копии, пока оригинал остаётся чистым и другие продолжают над ним работать.

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

main — это доверенная линия

Официальное, поставленное на полку издание книги, которому все доверяют, — черновики случаются в другом месте, и лишь законченная, одобренная работа вплетается в него.

По соглашению главная ветка зовётся main (в старых репо ещё встретишь master). Она призвана держать стабильную, рабочую версию проекта — ту, что ты бы выпустил. Новая работа случается на других ветках и присоединяется к main, лишь когда готова и отревьюена. Относиться к main как к доверенной линии, никогда как к черновику, — простая дисциплина за большинством здоровых командных процессов.

Переключение веток меняет твои файлы

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

Когда ты переключаешься (switch, или checkout) на ветку, Git меняет файлы в твоей папке, чтобы они совпали со снимком той ветки. Перейди на ветку фичи — и твои правки появляются; переключись обратно на main — и они исчезают из виду (безопасно сохранённые, не потерянные). Ветки в Git дёшевы и мгновенны, поэтому создавать по одной на фичу или починку — норма и поощряется: не тяжеловесный акт, а будничный ход.

Ветка — это параллельная линия работы, где ты свободно коммитишь, никого не беспокоя. main — доверенная версия; новая работа живёт на своей ветке, пока не готова.

§ 04

Работа, что разошлась по веткам, рано или поздно должна сойтись обратно. Слияние — это как Git воссоединяет линии, а конфликт — тот единственный момент, когда ему нужно, чтобы решил ты.

Слияние сводит две ветки обратно вместе

Вложить правки из своего отдельного черновика обратно в официальную рукопись, чтобы книга теперь содержала и оригинал, и твою новую главу.

Слияние (merge) объединяет коммиты одной ветки в другую — обычно вкладывая законченную ветку фичи обратно в main. Git смотрит, что изменилось с каждой стороны, и сплетает их в одну ленту, что содержит оба набора работы. Бо́льшую часть времени это автоматически и без усилий: две ветки тронули разные файлы или разные части, и Git просто сшивает их вместе.

Конфликт — это две правки одной строки

Два редактора, что оба переписали ровно одно предложение по-разному, — ни одна машина не знает, что ты имел в виду, так что она останавливается и спрашивает тебя.

Конфликт слияния (merge conflict) случается, когда обе ветки изменили одну часть одного файла несовместимо. Git не может угадать, какая версия верна, так что он ставит паузу, помечает место и показывает обе версии бок о бок. Это не ошибка и не катастрофа — это Git верно отказывается тихо выбросить чью-то работу. Конфликты пугают в первый раз ровно потому, что ставки (не потерять работу) ясны.

Разрешить конфликт — это просто выбрать

Прочитать оба переписанных предложения, потом написать финальную версию, что ты реально хочешь, — оставив одно, другое или смесь, — и идти дальше.

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

Слияние сплетает две ветки в одну ленту. Конфликт — это просто две правки одной строки: Git отказывается гадать и просит тебя выбрать.

§ 05

Пока что всё живёт на твоей машине. Работа с другими — или резервная копия твоей работы — означает соединить твой локальный репо с общим в облаке.

Локальный и удалённый — две копии

Твоя личная рабочая копия рукописи дома и общая мастер-копия в офисе, с которой вся команда держится в синхроне.

Git распределённый (distributed): у тебя есть полная копия репо на машине (локальная, local), и обычно есть общая копия на сервере (удалённая, remote) — на сервисе вроде GitHub или GitLab. Ты делаешь всю работу локально — быстро, даже офлайн — и синхронишься с удалённым, чтобы поделиться ею и подтянуть чужую работу. Удалённый по умолчанию по соглашению зовётся origin. Две копии, держимые в шаге нарочно.

Clone, push, pull, fetch

Ксерокопировать офисный мастер, чтобы унести домой (clone), отправить свои готовые страницы (push) и забрать новые страницы всех остальных (pull).

Четыре слова двигают работу между локальным и удалённым. Clone делает твою первую локальную копию удалённого репо. Push шлёт твои коммиты наверх на удалённый, чтобы другие их увидели. Pull приносит чужие новые коммиты вниз в твою копию. Fetch скачивает новое, не сливая пока, чтобы ты сперва посмотрел. Освой эти четыре — и сможешь сотрудничать: это вся лексика того, как держаться в синхроне.

Pull request — это как команды ревьюят работу

Подать свою новую главу редакторам, что читают её, комментируют и одобряют, прежде чем она вплетётся в официальную книгу.

На платформах вроде GitHub ты обычно не сливаешь прямо в main. Ты пушишь свою ветку и открываешь pull request (PR) — предложение слить твою работу, где сокомандники ревьюят её, оставляют комментарии и одобряют, прежде чем она присоединится к main. Это контрольная точка, где вторая пара глаз ловит проблемы, а команда соглашается, что изменение готово. PR — это где реально случается бо́льшая часть командного Git.

Локальный — твоя копия; удалённый (origin) — общая. Clone, push, pull и fetch держат их в шаге — а pull request это где команда ревьюит до слияния.

§ 06

Глубочайшее утешение Git в том, что почти ничто никогда по-настоящему не теряется. Знать, как читать историю и шагать назад безопасно, — вот что превращает Git из пугающего в успокаивающий.

Лог — это история проекта

Пролистывать датированную, подписанную стопку каждого черновика — видя ровно, что изменилось на каждом шаге и кто это сделал.

Лог (log) — это список коммитов, история твоего проекта по порядку, каждый со своим сообщением, автором и временем. Он отвечает на «что случилось и когда?» и это отправная точка для понимания любой кодовой базы или охоты за любым багом. Когда что-то ломается, лог даёт найти точный коммит, что это ввёл, потому что каждое изменение записано. История, что можно прочесть, — это история, что можно отлаживать.

Отменяй безопасно: revert против reset

Два способа отменить ошибку: добавить ясно помеченную поправку в запись (revert) или тихо вырвать последнюю страницу, будто её и не было (reset).

Git даёт безопасные пути назад. Revert создаёт новый коммит, что отменяет предыдущий, — ошибка остаётся в истории, с её отменой, записанной сверху, что честно и безопасно для общей работы. Reset двигает тебя назад к раннему коммиту, переписывая недавнюю историю, будто тех коммитов не было, — мощно, но опасно на работе, что у других уже есть. Правило большого пальца: revert в публичном, reset только на приватной, локальной работе.

Rebase переигрывает твою работу; уважай золотое правило

Вместо того чтобы пристегнуть свой боковой черновик к рукописи видимым швом (merge), ты заново чисто переписываешь свои правки поверх последней версии, будто стартовал с неё (rebase).

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

Лог — это читаемая история; revert и reset — твои пути назад. Rebase делает опрятную историю — но никогда не переписывай историю, что другие уже подтянули.

§ 07

Команд в Git много, но хорошая практика — это короткий список привычек. Следуй им, и Git остаётся спокойной страховочной сетью, а не редкой аварией.

Маленькие, сфокусированные коммиты с ясными сообщениями

Фотоальбом, где каждый снимок ловит один ясный момент с подписью, — куда полезнее одного смазанного кадра всего разом.

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

Ветка на фичу, сливаемая часто

Каждая новая глава черновится на своей копии и вкладывается обратно, пока ещё мала, — чтобы ни один черновик не ушёл от книги так далеко, что воссоединить его станет битвой.

Делай каждый кусок работы на своей ветке, держи её короткоживущей и сливай обратно часто. Долгоживущие ветки уходят далеко от main и превращают слияние в болезненную кучу конфликтов; маленькие ветки, сливаемые часто, остаются лёгкими. Сочетай это с pull перед push — сперва внеси чужие изменения — чтобы интегрироваться непрерывно, а не сталкиваться в конце. Этот ритм — сердце гладкого командного Git.

Твои будничные привычки Git
  • Подтяни последнее (pull) перед началом, чтобы строить на текущей работе. - Работай на ветке, никогда прямо на хрупком main. - Делай маленькие коммиты с ясными сообщениями по ходу. - Сливай часто, пока ветки ещё короткие, чтобы держать конфликты крошечными. - Пушь свою работу и открывай pull request на ревью. - Отменяй через revert на общей работе; никогда не делай rebase истории, что у других есть.
Слова, которыми ты теперь владеешь
  • репозиторий / коммит / сообщение — отслеживаемый проект, один снимок и его записка. - staging area / HEAD — коробка, что пакуешь перед коммитом, и маркер «ты здесь». - ветка / main — параллельная линия работы и доверенная версия. - merge / конфликт — воссоединение веток и столкновение на одной строке, что разрешаешь. - local / remote / origin — твоя копия, общая копия и её имя по умолчанию. - clone / push / pull / fetch — четыре хода, что держат копии в синхроне. - pull request / revert / reset / rebase — ревью, безопасная отмена и переписывание истории.
Признаки, что ты используешь Git хорошо
  • Твоя история читается как ясный рассказ из маленьких, подписанных шагов. - Новая работа живёт на ветках; main всегда работает. - Ты делаешь pull перед push и сливаешь, пока ветки ещё малы. - Ты тянешься к revert на общей работе и никогда не переписываешь общую историю. - Git ощущается страховочной сетью — ты свободно экспериментируешь, зная, что всегда вернёшься.

Хороший Git — это несколько привычек: сперва pull, ветка под работу, маленькие коммиты с ясными сообщениями, частые слияния и ревью до слияния. Команд много; дисциплина коротка.

Конец экспресс-курса · 7 глав · выучи слова

Дальше — практика: возьми любой маленький проект, запусти git init и сделай несколько коммитов по мере изменений — потом создай ветку, сделай правку и слей обратно. Намеренно вызови конфликт, отредактировав одну строку на двух ветках, и разреши его. Страх испаряется в тот миг, как ты сделал каждое раз на том, что не важно. Но держи одну мысль выше прочих: Git — это кнопка сохранения, что не забывает, и способ для многих людей работать, не затирая друг друга. Каждое пугающее слово — просто имя одному спокойному, восстановимому шагу, — и теперь они все у тебя есть.