Git/refactoring

Материал из ALT Linux Wiki


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

Рассмотрим git add --patch, git stash, git rebase --interactive.

Вводная

Основная идея переписывания истории в том, чтобы уже сделанные изменения оформить по-другому.

Например:

  • разбить один commit на несколько -- после активной доработки напильником сделанные изменения привести в вид отдельных commit'ов, с комментариями объясняющими зачем нужно именно это изменение;
  • объединить несколько commit'ов в один -- сделали патч, потом нашли в нем багу и сделали исправление, и все это до публикации результата, разумно публиковать не "историю как мы мучались с этим патчем", а "историю изменений";
  • переупорядочивание commit'ов -- часто необходимо для использования остальных инструментов переписывания истории;
  • rebase -- приложить имеющийся набор патчей к другому бранчу (например мы хакали, хакали, а апстрим взял и обновился)

git add --patch

Удобный инструмент разделения commit'а на несколько.

Например, налепил на скору руку коммитов для фиксации состояния и читабельного git diff, а потом затарил на всякий, git reset --soft на последний нормальный коммит, делаешь git status и смотришь: этот файлик целиком git add, а в этом правки, которые растащить по разным коммитам бы надо, вот его git add --patch и по hunk'ам принимаешь или оставляешь на потом.

Набил будущий коммит в индекс, git commit его и дальше по git diff.

git stash

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

Запихиваешь (stash) на «полку» всё незакоммиченное, делаешь мыслю, мержишь апстрим либо что ещё там — и git stash apply, который сбегает в заначку и приспособит её поверх текущего состояния. Только в случае с «откладываешь» перед apply стоит git stash list, вдруг там больше одного набилось. Чтобы "полка" не забивалась старыми и неактуальными более заначками, лучше делать git stash pop $id - это применит отложенную работу и удалит её из списка.

git rebase --interactive

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

Пусть надо переработать 10 последних патчей, делаем:

  $ git rebase -i HEAD~10

что запустит $EDITOR и покажет нечто вроде:

  # Rebasing 16d3800..14f3d11 onto 16d3800
  #
  # Commands:
  #  pick = use commit
  #  edit = use commit, but stop for amending
  #  squash = use commit, but meld into previous commit
  #
  # If you remove a line here THAT COMMIT WILL BE LOST.
  #
  pick 6270640 Simplify write_tree using strbuf's.
  pick 27c528a Further strbuf re-engineering.
  pick fd82c9a Eradicate yet-another-buffer implementation in buitin-rerere.c
  pick eee488f More strbuf uses in cache-tree.c.
  pick 16878b5 Add strbuf_rtrim and strbuf_insert.
  pick e9081af Change semantics of interpolate to work like snprintf.
  pick 99c3ef5 Rework pretty_print_commit to use strbufs instead of custom buffers.
  pick 203db5d Use strbuf_read in builtin-fetch-tool.c.
  pick a20d939 Use strbufs to in read_message (imap-send.c), custom buffer--.
  pick 14f3d11 Replace all read_fd use with strbuf_read, and get rid of it.
  ~
  ~

Здесь можно заменить pick на edit, если хочется поменять что-нибудь в коммите, или на squash, чтобы объединить его с тем, который строчкой выше.

Подсказка не говорит явно, но возможно также и изменять порядок коммитов.

Ссылки