Bash команды для оптимизации работы с Git

Bash команды для оптимизации работы с Git
Bash команды для оптимизации работы с Git

Чем больше вы работаете с 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, но не может ̶с̶п̶у̶л̶и̶т̶ь̶ скачать последние изменения, он остановится, вместо того, чтобы продолжать и перемещать в вашу ветку потенциально устаревшие изменения.

Приведенный выше алиас, будет выполнять следующие шаги, до тех пор, пока один из них не завершится с ошибкой:

  1. Переход на master (или заданную ветку)
  2. Обновление до актуального состояния
  3. Возвращение на ветку, где мы изначально находились
  4. Интерактивный перенос ветки master в текущую ветку

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

Про другие команды управления вы можете почитать в документации bash.

Стоп, зачем использовать алиасы?

Вы можете задаваться вопросом: «Разве я не могу просто написать bash скрипты?»

Технически — да, вы можете. Преимущество в данном случае в контексте. Все эти команды состоят из различных git-команд. Функция в вашем bash профиле будет запущена, где бы вы ее ни запустили.

Создав же эти скрипты в виде git-алиасов, вы обеспечиваете то, что они будут запущены только в git-репозиториях. К тому же вам не нужно добавлять что-то к имени функций, чтобы избежать проблем с неймспейсами: git-Function или gitFunction. Если вы делали это, то алиас будет в самый раз.

Я надеюсь вы нашли вдохновение от моих команд и поняли как создавать свои собственные.

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

Статью перевел aziev. Оригинал на Medium.freecodecamp.com доступен по ссылке.

Автор

MIIIG

Занимаюсь разработкой сайтов, знаю php, js, html, css, gulp, bash, увлекаюсь разработкой на микроконтроллерах(esp, arduino), перевожу статьи, также увлечен графическим дизайном, типографией, знаю также немного арабский, люблю минимализм, простоту и material design