Чем больше вы работаете с Git, тем больше его возможностей используете.
Перечислю несколько задач, которые я и моя команда выполняем каждый день:
- Создание веток и их именование
- Подсчет коммитов для объединения
- Обновление master до последнего состояния с последующим переносом на новую ветку
Но каждая из этих задач требует выполнения нескольких шагов. Это заставило меня задуматься: должен быть более удобный способ чтобы это сделать.
К счастью, более удобный способ есть! Немного изучив Bash, вы можете создать Git-алиасы, которые смогут сохранить уйму вашего времени.
Первым делом: Git флаг «!»
Вы когда-нибудь видели Git-алиас c восклицательным знаком вначале? К примеру:
somealias = "!......some code"
Исходя из документации Git, если алиас имеет префикс в виде восклицательного знака, он будет обработан как shell-команда.
Классно! Мы можем использовать это для своих целей и довести до ума наши алиасы. Давайте начнем с простого примера и будем усовершенствовать его по ходу дела.
Откройте .gitconfig файл в любом текстовом редакторе и добавьте следующий алиас:
hello = "!echo \"Hello World\""
# (обратные слэши экранируют кавычки.)
Теперь, если вы выполните git hello в консоли, вы увидите «Hello World». Отлично! Вооружившись этим, давайте посмотрим на 3 примера, которые приводились ранее, и алиасы, которые я использовал для их реализации.
Создание веток и их именование
Алиас:
newb = "!f() { ticketnum=$1; branchName=$2; git checkout -b \"POD-${ticketnum}/${branchName}\"; }; f"
Использование:
# Создает новую ветку POD-573/my-new-feature
$ git newb 573 my-new-feature
Ключевые команды:
- Функция: f(){}; f
- Параметры: $1, $2
- Интерполяция строк: ${ticketnum}, ${branchName}
В нашей команде мы перед именем ветки ставим номер карты в нашей системе квитанций. Например, «POD-573/my-new-feature». Это название используется в нашей системе, чтобы объеденить все данные вместе, поэтому для нас важно придерживаться таких правил.
Функция
В bash вы можете написать функцию вот так: FunctionName(){}; FunctionName. Написание имени функции после ее определения запускает ее выполнение. В моих алиасах я сократил имя функции до f для краткости.
Когда bash запускает f, будет выполнен весь код заключенный между фигурными скобками {}. В нашем случае функция запускает git checkout -b «MESSAGE».
Параметры
Параметры следуют непосредственно после команды. Например, команда перемещения файла в bash:
$ mv ./file.txt ./folder/file.txt
Первый параметр, который принимает команда mv, это ./file.txt. Этот параметр автоматически привязывается к $1 в bash. Таким же образом ./folder/file.txt привязывается к $2. В функции алиаса вы можете использовать это, назначая более осмысленные имена переменных для этих параметров.
# развернуто для читаемости
!f() {
# much more meaningful!
ticketnum=$1;
branchName=$2;
git checkout -b \"POD-${ticketnum}/${branchName}\";
};
f
Интерполяция строк
Для использования переменных в bash, вы просто добавляете знак доллара в начало имени: $ticketnum. В данном случае функция вставляет переменную в строку.
В то время как bash позволяет выполнить интерполяцию напрямую, используя переменную, я предпочел использовать похожий синтаксис, который поддерживается многими языками программирования: ${variable}.
В нашем примере, когда bash подставит значения переменных в POD-${ticketnum}/${branchName}, строка примет вид: POD-573/my-new-feature.
Подсчет коммитов
count = "!f() { compareBranch=${1-master}; git rev-list --count HEAD ^$compareBranch; }; f"
Использование:
# Было сделано 5 коммитов с момента ответвления
$ git count #вернет 5
# Передайте другую ветку для подсчета, вместо master $ git count dev
Ключевые команды:
- Передача параметра: ${1-DEFAULT}
- Подсчет доработок: rev-list —count
Передача параметра
Как и при строковой интерполяции, переменная compareBranch присваивается используя ${} синтаксис. Это дает возможность установить значение по умолчанию, если параметр не был передан при вызове команды. В нашем алиасе compareBranch=${1-master} будет использовать ветку master для работы, если ничего не пришло из консоли.
# предполагается master
$ git count
# compareBranch установлен как dev
$ git count dev
Вы можете почитать подробнее про передачу параметров в документации bash.
Подсчет доработок
По умолчанию команда git rev-list вернет SHA-хэши связанные с заданной веткой. Если добавить флаг —count, вместо этого будет возвращено общее количество коммитов в конкретной ветке. Наша цель — получить число коммитов, созданных со времени ответвления от master (или любой другой ветки). Для этого мы должны передать имя ветки с оператором ^.
$ git rev-list --count HEAD ^master
Эта команда говорит git: Я хочу получить количество коммитов, доступных для HEAD (текущей ветки), но не доступных для master.
Если вы создали 5 коммитов со времени ответвления от master, команда вернет 5.
Объединение X коммитов
Алиас:
squashbase = "!f() { branchName=${1-master}; commitCount=$(git count $branchName); git rebase -i HEAD~$commitCount; }; f"
Использование:
# Получение количества коммитов для объединения # и начало интерактивного перемещения. $ git squashbase
# необязательная передача ветки $ git squashbase dev
Ключевые команды:
- Подстановка команды: $(COMMAND)
Подстановка команды
Эта команда довольно прикольная. Скрипт снова использует branchName по умолчанию для подстановки ветки master, но второй параметр использует новый синтаксис $(). Это называется «подстановка команды (command substitution)». Когда bash видит команду в круглых скобках, он преобразует это выражение и использует вывод как значение переменной. К примеру, x=$(echo «Hello») будет преобразовано к x, выводящему значение Hello.
В данном случае, алиас вызывает предыдущий алиас, подсчитывающий количество коммитов. Если предположить, что в текущей ветке сделано 5 коммитов с момента отвлевления от master, команда $ git squashbase будет преобразона к $ git rebase -i HEAD~5. Эта команда начинает интерактивный rebase с последними 5 коммитами, предоставляя вам возможность подчистить ваши коммиты.
Обновление master и перенос в ветку
Алиас:
pullbase = "!f() { branchName=${1-master}; git checkout $branchName && git pull && git checkout - && git rebase -i $branchName; }; f"
Использование:
# Переключить ветку, сделать pull, вернуться на предыдущую ветку с сделать rebase.
$ git pullbase
$ git pullbase dev
Ключевые команды:
- Команда «тире»: —
- Команда управления: &&
Команда «тире»
Здесь все должно быть понятно. Сокращение используется чтобы долго не печатать. Тире — это ссылка на последнюю ветку, с которой вы переключились на текущую. Это как кнопка «назад» на пульте от телевизора.
Cледующий пример наглядно это демонстрирует:
# на ветке dev
$ git checkout master # теперь на ветке master
$ git checkout - # вернуться на dev
$ git checkout - # вернуться на master branch
Команда управления
В bash есть много способов связать операции в цепочку. Самый мой любимый — использование &&.
Преимущество этой команды в том, что она остановит выполнение, если предыдущая команда завершилась с ошибкой. Если git переходит на master, но не может ̶с̶п̶у̶л̶и̶т̶ь̶ скачать последние изменения, он остановится, вместо того, чтобы продолжать и перемещать в вашу ветку потенциально устаревшие изменения.
Приведенный выше алиас, будет выполнять следующие шаги, до тех пор, пока один из них не завершится с ошибкой:
- Переход на master (или заданную ветку)
- Обновление до актуального состояния
- Возвращение на ветку, где мы изначально находились
- Интерактивный перенос ветки master в текущую ветку
В нашей компании требуется, чтобы каждый наш пулл-реквест содержал отдельный коммит, прежде чем он будет слит с master. Поэтому я запускаю эту команду несколько раз в день и она сохранила мне довольно много времени с тех пор, как я стал ее использовать.
Про другие команды управления вы можете почитать в документации bash.
Стоп, зачем использовать алиасы?
Вы можете задаваться вопросом: «Разве я не могу просто написать bash скрипты?»
Технически — да, вы можете. Преимущество в данном случае в контексте. Все эти команды состоят из различных git-команд. Функция в вашем bash профиле будет запущена, где бы вы ее ни запустили.
Создав же эти скрипты в виде git-алиасов, вы обеспечиваете то, что они будут запущены только в git-репозиториях. К тому же вам не нужно добавлять что-то к имени функций, чтобы избежать проблем с неймспейсами: git-Function или gitFunction. Если вы делали это, то алиас будет в самый раз.
Я надеюсь вы нашли вдохновение от моих команд и поняли как создавать свои собственные.
Если у вас уже есть свои любимые алиасы или что-то другое, упрощающее работу с git, поделитесь этим в комментариях, чтобы мы вместе могли изучить их и, возможно, сэкономить много нашего времени.
Статью перевел aziev. Оригинал на Medium.freecodecamp.com доступен по ссылке.