Минимальный жизнеспособный Git для разработки на основе магистрали

Nov 30 2022
Чем меньше, тем лучше, когда речь идет о таком мощном и слишком сложном инструменте, как Гит Эли, соучредитель и со-генеральный директор trunk.io.

Чем меньше, тем лучше, когда речь идет о таком мощном и слишком сложном инструменте, как Git.

Эли является соучредителем и со-генеральным директором trunk.io . Он занимал руководящие должности инженеров в Microsoft, Uber и Google (которая приобрела стартап, соучредителем которого он является). Его основная задача — помочь командам быстрее создавать лучшее программное обеспечение.

Git Inferno Данте

Разработка в среде для совместной работы — это сложная операция, которая включает в себя отслеживание и координацию работы нескольких разработчиков. Многие из нас используют Git для управления версиями, чтобы контролировать все эти изменения. Но, по словам самого Линуса , Git — это «информационный менеджер из ада». Он предлагает так много опций и странных состояний, что вы можете легко оказаться в плохом положении до такой степени, что вам нужно повторно клонировать с нуля, даже если вы не сделали ничего плохого.

Многие из нас знают, что один разработчик изучил refspec Git и базовое дерево Меркла, на котором оно основано, но быть специалистом по Git, вероятно, не входит в ваши должностные обязанности. Я могу отлично водить машину, не понимая, как на самом деле работает трансмиссия, и, в конце концов, Git — это просто средство для достижения цели.

Чтобы получить максимальную отдачу от Git, вы должны использовать его как можно меньше , когда речь идет о разработке на основе магистралей. Ограничьте количество используемых команд, своевременно обновляйте свою ветку функций и стандартизируйте использование в команде. В индивидуальном порядке вы можете наслаждаться свободой делать все, что захотите. Но в команде за свободу приходится платить трениями.

Ограничьте свои действия с Git

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

Однажды технический директор попросил меня провести курс по продвинутому git для его инженерной команды. Мой ответ был прост:

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

Вот 10 git-команд, которые я использую, чтобы выполнить свою работу и свести к минимуму количество попаданий в Git-ад:

Управление филиалом

git checkout -t -b {branch-name}
Создайте ветку, установите восходящий поток на текущую ветку и переключитесь на нее. Вы также можете сделать это с помощью команды `git branch`, но для этого потребуется несколько команд. Так как я всегда хочу переключиться на ветку при ее создании, эта команда более краткая. Создайте и проверьте ветку одним махом. Обычно я называю все свои ветки eli/{work-being-done}.

git checkout {branch-name}
Переключитесь на ветку.

git branch -vv
Просмотрите свои текущие ветки и их восходящие потоки.

git branch -D {branch-name}
Удалите локальную ветку, обычно для очистки устаревших/объединенных веток.

Толкание и вытягивание

git fetch origin main:main
Вставьте пульт mainв свой локальный main, даже если вы сейчас не в mainветке! Это ; очень полезно, когда вы пытаетесь слить последнюю mainверсию в ветку PR.

git push origin
Отправьте мой код на пульт; вероятно, раскрутил много машин в CI, чтобы проверить мою работу.

git pull
Обновите мою локальную ветку с помощью пульта с таким же именем.

Совершение

git add -A .
Добавить все, над чем я работаю (новые и отредактированные файлы).

git commit -am "work"
См. здесь для глубокого погружения в мои мысли о сообщениях локальных коммитов

git merge main
Подробнее об этом ниже. Я прагматичен, а не ребазер, и рад замутить свою локальную ветку происходящим из main.

Держите свою ветку функций в актуальном состоянии должным образом

В моей последней части я обсуждал, как управлять посадочным кодом на main. Но часто во время разработки и, конечно же, перед слиянием вам необходимо быть в курсе последних изменений, mainпотому что:

  • Вам нужна какая-то функция, которая приземлилась, mainчтобы выполнить вашу функцию.
  • Что -то mainизменилось, и если вы этого не поймете, вы сломаете его, когда попытаетесь загрузить свой код.
  • Вы просто хотите оставаться свежим, потому что вы инженер и любите блестящие новые вещи.

Дверь 1: слияние git

Это моя стратегия слияния. Он простой, надежный и без излишеств. Базовый git mergeберет все произошедшие изменения mainи объединяет их вместе как коммит вместе с вашими изменениями. Вы можете до тошноты читать о недостатках этого решения без излишеств, но я, честно говоря, просто пожимаю плечами и говорю: «Меня это не волнует». Если вы объедините свои рабочие ветки main, то вся эта ерунда о загрязнении git-log станет просто так.

Честно говоря, на самом деле не имеет значения, как/почему/что попало в мою рабочую ветку. Важно то, строится ли он, работает ли он и делает ли код то, что я хочу? Остальное академично.

На практике, а я очень практичный инженер, git mergeпозволяет вам аккуратно справляться с конфликтами слияния и возвращаться к построению. Вы разрешаете любые конфликты слияния один раз — и все готово. Это лучший вариант для начинающих, занятых продвинутых пользователей и тех из вас, кто не мечтает стать гуру Git.

Дверь 2: git rebase

Это худший вариант на сегодняшний день. Хорошо, я знаю; есть практически целое поколение, которое рассматривает перебазирование и слияние чего-то вроде вкладок и пробелов. Но в «реальных» проектах, где одна или несколько команд ежедневно объединяются в репозиторий, rebase требует разрешения n конфликтов слияния вместо одного с помощью слияния или сквоша (подробнее об этом ниже).

Кроме того, любое перебазирование перезаписывает историю Git, а это означает, что если у вашей ветки есть удаленный аналог, вам нужно git push --forceтопать ее историю новой перебазированной историей вашей ветки. Теоретически это хорошо, но существует вероятность того, что ваша предыдущая работа будет случайно удалена, и восстановить ее будет крайне сложно. Это просто намного опаснее, чем слияние, и, честно говоря, у меня голова болит от одной мысли об этом.

Для целей этой статьи я попытался перебазировать, просто чтобы напомнить себе, как сильно я не люблю этот рабочий процесс. Посмотрите, что выводит на мой терминал простая команда rebase:

хорошие рабочие процессы не должны требовать подсказок для работы

С этим терминалом столько всего не так. Я получаю заметки о хэшах коммитов — не хочу их видеть. Я получаю четыре строки желтых подсказок, чтобы напомнить мне, как все это работает. И сейчас я нахожусь в каком-то рабочем процессе, чтобы получить код из mainсвоей ветки. Дерево решений глупо сложно; git rebase --skip- что это?! Почему можно пропустить коммит? Знаешь что? Не говорите мне, потому что у меня есть работа.

Дверь 3: git squash rebase

Вам определенно не нужно то, что находится за дверью № 2, но некоторые люди являются несгибаемыми ребакерами. Мой соучредитель, со-генеральный директор Дэвид Апирян, показал мне свой секретный вход за кулисы в rebase, и это довольно круто. Мы назовем это перебазированием сквоша .

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

  • Посмотрите различия ваших локальных коммитов, прежде чем отправлять их на GitHub.
  • Легко отменить последнюю фиксацию.
  • Не загрязняйте представление GitHub о вашем запросе на вытягивание кучей небольших локальных коммитов.

Шаг 1 — раздавить все ваши локальные коммиты:

git reset --soft $(git merge-base HEAD main) &&
git commit -am "" --allow-empty-message

git rebase main

Вы можете объединить все это в одну убер-команду, чтобы получить последний основной файл, сжать все ваши коммиты и перебазировать последний основной файл:

git reset --soft $(git merge-base HEAD main) &&
git commit -am "" --allow-empty-message &&
git fetch origin main:main &&
git rebase main

[alias]
 smartcommit = !git add -A . && git commit -am "" --allow-empty-message
 squash = !git reset --soft $(git merge-base HEAD main) && git commit -am "" --allow-empty-message
 squashrebase = !git squash && git fetch origin main:main && git rebase main
 smart = !git smartcommit && git squashrebase

Один из самых крутых аспектов постоянного раздавливания ваших локальных коммитов заключается в том, что в верхней части ваших коммитов git logнаходится вся работа, которую вы проделали в ветке. Ваша локальная работа теперь больше похожа на то, как будет выглядеть объединенный PR в сквоше, когда он попадет в main.

Вы можете в любой момент вытащить последний коммит из HEAD в свою локальную ветку и увидеть всю работу, которую вы проделали из main. Это похоже на подробное представление изменений, которое GitHub предоставляет вам, но позволяет вам оставаться в своем терминале и избегать путаницы при переключении между двумя разными пользовательскими интерфейсами.

Должен признаться, что когда Дэвид впервые показал мне этот рабочий процесс, я был впечатлен. Он в основном убил rebaseдракона, и возможность локального просмотра всех файлов, которые вы изменили в своей ветке, очень крутая.

В то время как сквош-перебазирование помогает вам поддерживать лучшее состояние потока, подавляющее большинство разработчиков предпочитают просто слияние. Неправильное использование rebase или squash rebase приводит к трениям, которые убивают производительность.

Подводные камни справки ветки GitHub

эти флажки в GitHub кажутся полезными… но они не

GitHub предлагает этот параметр ☝️, чтобы предлагать mainавтоматическое слияние с вашей веткой, если она устарела. Этот параметр часто контрпродуктивен. Я хочу, чтобы моя локальная ветка была единственным источником правды для моего пиара, и никто другой (включая GitHub) не должен на это напирать. Работа с GitHub в моей личной ветке должна быть улицей с односторонним движением. Я кодирую локально и нажимаю.

Если вы настроите GitHub так, чтобы он начал отправлять обновления в вашу рабочую ветку, вы просите, чтобы трафик начал двигаться в неправильном направлении. И это рецепт боли.

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

Я часто обнаруживаю, что случайно сделал это с собой, когда пытаюсь отправить свои обновления обратно на удаленный компьютер, а git сообщает мне, что я не синхронизирован. В этот момент у меня есть два варианта:

  1. git push --forceи сдуйте все на удалении, а не в вашей локальной ветке. Обычно все, что связано со словом сила, разрушительно и обескураживает.
  2. git merge origin/{my-work-branch}чтобы объединить удаленные изменения с локальным представлением ветки.

Этот параметр GitHub ️☝️ требует, чтобы PR были обновлены mainперед слиянием с ним. Обычно это «решает» возможность поломки main; однако он работает только с репозиториями с очень низкой скоростью. Как только несколько разработчиков пытаются объединить несколько PR в день, они вступают в гонку за слияние main— или иным образом обнаруживают, что постоянно выполняют слияние/перебазирование mainв свою ветку, чтобы снова быть «актуальными», и в основном соревнуются со своими коллегами. быть первым, чтобы слиться. Болезненный. Как правило, если вам нужна эта функция, но вы не являетесь разработчиком-одиночкой, вам, вероятно, вместо этого нужна очередь слияния — это масштабируемый способ добиться отсутствия поломки основного. Это то, что мы сочли достаточно важным для реализации с помощью Trunk Merge .

Минимизируйте Git для получения максимальной выгоды

Максимально упрощая использование Git, вы даете разработчикам меньше веревки, на которой можно повеситься, и больше времени для выполнения действительно важной работы по разработке. Заставьте Git играть вспомогательную роль, а не стать главным героем. Чтобы поддерживать разумную и совместную среду разработки, не забудьте:

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