Skip to content

Instantly share code, notes, and snippets.

@radist2s
Created October 10, 2023 12:01
Show Gist options
  • Save radist2s/99a028b977abeb05113e3265ace4f7b2 to your computer and use it in GitHub Desktop.
Save radist2s/99a028b977abeb05113e3265ace4f7b2 to your computer and use it in GitHub Desktop.
Рекомендации по использованию Git для поддержания чистоты дерева изменений

Amend Commit

git commit --amend -m "New commit message"

Эта команда позволяет изменить сообщение последнего коммита на "New commit message".

🧹 Перезапись хеша: Поскольку содержание коммита изменяется (хотя бы сообщение), хеш коммита тоже изменится. Это, в свою очередь, приведёт к изменению хешей всех последующих коммитов, если таковые имеются.

  1. Осторожно с "публичными" ветками: Если ты уже запушил коммит, а потом решил его "исправить" и снова запушить, тебе придётся использовать git push --force для перезаписи истории на удалённом репозитории. Это может создать проблемы для других разработчиков, которые уже вытащили обновления.

Fixup Commit

git add fixed-file.ts
git commit --fixup <SHA-of-commit-to-fix>

После создания одного или нескольких fixup коммитов, вы можете выполнить интерактивный rebase с опцией --autosquash, которая автоматически упорядочит и объединит fixup коммиты с их родительскими коммитами:

git rebase -i --autosquash <base-commit>~1

Параметр ~1 означает, что rebase начнется с коммита, предшествующего указанному .

🧹 Перезапись хеша

Interactive Rebase

  1. Выбор базового коммита: Определи хеш коммита, начиная с которого ты хочешь провести rebase (назовем его <base-commit>). Этот коммит будет тем, на котором будут "основаны" твои измененные коммиты.

    git log
  2. Запуск интерактивного rebase:

    git rebase -i <base-commit>~1

    Параметр ~1 означает, что rebase начнется с коммита, предшествующего указанному

  3. Выбор действий: После запуска команды вы увидите текстовый редактор с перечнем коммитов. Здесь ты можешь выбрать, что именно хочешь сделать с каждым коммитом: pick, reword, edit, squash, fixup, и т.д.

  4. Применение изменений: После сохранения и закрытия редактора, Git начнет применять изменения. Если возникнут конфликты, их нужно будет решить вручную.

  5. Завершение rebase:

    git rebase --continue

Git Rerere

git rerere (REuse REcorded REsolution) — это утилита в Git, которая помогает автоматизировать процесс решения конфликтов при слиянии или ребейзе. В основном, это полезно, когда ты часто сталкиваешься с одними и теми же конфликтами и не хочешь решать их вручную каждый раз.

Вкратце, работает это так:

  1. При включении git rerere для локального репозитория:
    git config rerere.enabled true
    или глобально:
    git config --global rerere.enabled true
    Git начинает запоминать, какие конфликты возникают и как ты их разрешаешь.
  2. При следующем возникновении аналогичного конфликта Git автоматически применяет те же изменения, чтобы разрешить конфликт.

Выключить rerere можно так:

git config --unset rerere.enabled

Rerere Issues Resolution 🥸

Основные команды:

  • git rerere — повторно применяет предыдущие решения по конфликтам, если таковые имеются.
  • git rerere remaining — показывает файлы, которые ожидают решения.
  • git rerere diff — показывает различия между сохраненным решением и текущим состоянием.
  • git rerere forget <path> — "забывает" решение конфликта для указанного файла.

Часто это применяется в больших командах или при работе с несколькими ветками, чтобы сократить время на разрешение конфликтов.

Q&A:

  • Q: Как обновить yarn.lock в для отдельного коммита?

  • A:

    • Для последнего коммита: git add yarn.lock && git commit --amend --no-edit
    • Interactive Rebase → Amend Commit
  • Q: Как разделить коммит на несколько?

  • A: Interactive Rebase + git reset HEAD~ Splitting a commit into multiple commits

  • Q: Зачем нужен делать отдельные коммиты для отдельных групп изменений?

  • A:

    • Чтобы можно было откатить только часть изменений, а не все.
    • Чтобы можно было отбросить часть изменений, а не все (например, обновление файлов переводов).
    • Чтобы можно было откатить изменения, которые не должны были попасть в коммит (например, отладочный вывод).
    • Чтобы сделать cherry-pick только нужных изменений и создать отдельный MR в будущем
  • Q: Зачем разделять MR на несколько?

  • A:

    • Проще объяснить суть изменений/рефакторинга в отдельном MR, если они не связаны с решением задачи.
    • Чтобы можно было откатить только часть изменений, а не все решение задачи, и наоборот.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment