Skip to content

Instantly share code, notes, and snippets.

@webuxmotion
Forked from AMashoshyna/Kottans Git Workshop.md
Created January 26, 2020 15:01
Show Gist options
  • Select an option

  • Save webuxmotion/b3f88f2cd0b24e0b9ebad0e0270bca40 to your computer and use it in GitHub Desktop.

Select an option

Save webuxmotion/b3f88f2cd0b24e0b9ebad0e0270bca40 to your computer and use it in GitHub Desktop.

Revisions

  1. @AMashoshyna AMashoshyna revised this gist Jan 26, 2020. 1 changed file with 6 additions and 3 deletions.
    9 changes: 6 additions & 3 deletions Kottans Git Workshop.md
    Original file line number Diff line number Diff line change
    @@ -21,7 +21,7 @@
    Упражнение
    Исходное положение: коммит 0
    Шаг 1. Создать ветки feat-1 и feat-2 от коммита 0. В каждую из веток добавить по 2-3 коммита, изменяющих один файл.
    Объединить ветки при помощи git merge. Посмотреть, как выглядит история при помощи команды `git logg`.
    Объединить ветки при помощи git merge. Посмотреть, как выглядит история при помощи команды `git logg`*.
    Повторить Шаг 1
    Объединить ветки при помощи `git rebase`. Посмотреть, как выглядит история при помощи команды `git logg`. Обратить внимание на изменение хешей коммитов при rebase

    @@ -44,5 +44,8 @@

    ## Git в распределенной команде

    Стратегии Git (например, ГитФлоу) позволяют дают готовое решение для разделения и изоляции работу таким образом, чтобы отдельные команды (или люди) работающие на проектом, не мешали друг другу. Например, тестировщики и разработчики не мешают друг другу.
    Как правило, разработчик создает для своей задачи отдельную ветку от ветки master, делает задачу и вливает свою ветку в master через пул-реквест. В зависимости от проекта и выбранной стратегии промежуточных этапов между завершением работы над задачей и попаданием кода в master может быть несколько - бывают отдельные ветки dev, qa, stage (названия примерные). Каждая такая ветка может быть залита (задеплоена) на отдельную машину, где часть команды (разработчики, тестировщики, продакт-оунер) может протестировать код.
    Стратегии Git (например, ГитФлоу) позволяют дают готовое решение для разделения и изоляции работ таким образом, чтобы отдельные команды (или люди) работающие на проектом, не мешали друг другу. Например, тестировщики и разработчики работают со своей веткой и на своем сервере и не мешают друг другу.
    Как правило, разработчик создает для своей задачи отдельную ветку от ветки master, делает задачу и вливает свою ветку в master через пул-реквест. В зависимости от проекта и выбранной стратегии промежуточных этапов между завершением работы над задачей и попаданием кода в master может быть несколько - бывают отдельные ветки dev, qa, stage (названия примерные). Каждая такая ветка может быть залита (задеплоена) на отдельную машину, где часть команды (разработчики, тестировщики, продакт-оунер) может протестировать код.


    *`git logg` - это алиас для графического представление дерева коммитов: `"log --graph --full-history --all --color --pretty=tformat:\"%x1b[31m%h%x09%x1b[32m%d%x1b[0m%x20%s\""`. Этот алиас будет доступен тем, кто настроил окружение согласно [нашей инструкции](https://github.com/OleksiyRudenko/dev-env-git).
  2. @AMashoshyna AMashoshyna revised this gist Jan 26, 2020. 1 changed file with 13 additions and 12 deletions.
    25 changes: 13 additions & 12 deletions Kottans Git Workshop.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    ## `git rebase`

    В общем случае команда `git rebase` добавляет все коммиты из ветки, на которой вы находитесь, следующими за коммитом, который вы передаете `git rebase` как аргумент. Если передать первым аргументом ветку, Git найдет последний общий коммит между текущей веткой и целевой веткой и добавит коммиты из текущей у целевую один за одним. Можно представить себе, что `git rebase` по очереди "накатывает" каждый из коммитов вашей ветки на целевой коммит. При этом у всех "накатанных" коммитов изменяются метаданные (например, родительский коммит), поэтому с точки зрения Git это теперь новые коммиты.
    В общем случае команда `git rebase` добавляет все коммиты из ветки, на которой вы находитесь, следующими за коммитом, который вы передаете `git rebase` как аргумент. Если передать первым аргументом ветку, Git найдет последний общий коммит между текущей веткой и целевой веткой и добавит коммиты из текущей в целевую один за одним. Можно представить себе, что `git rebase` по очереди "накатывает" каждый из коммитов вашей ветки на целевой коммит. При этом у всех "накатанных" коммитов изменяются метаданные (например, родительский коммит), поэтому с точки зрения Git это теперь новые коммиты.

    На семинаре мы познакомились с двумя случаями применения `git rebase`.

    @@ -18,23 +18,24 @@
    Дополнительно:
    Гит присваивает коммитам хеши и различает коммиты по хешам. Рекомендуем почитать о том, как работют хеш-функции (на семинаре эта тема не рассматривалась)

    Упражнение
    Исходное положение: коммит 0
    Шаг 1. Создать ветки feat-1 и feat-2 от коммита 0. В каждую из веток добавить по 2-3 коммита, изменяющих один файл.
    Объединить ветки при помощи git merge. Посмотреть, как выглядит история при помощи команды `git logg`.
    Повторить шаг 1
    Объединить ветки при помощи `git rebase`. Посмотреть, как выглядит история при помощи команды `git logg`. Обратить внимание на изменение хешей коммитов при rebase
    Упражнение
    Исходное положение: коммит 0
    Шаг 1. Создать ветки feat-1 и feat-2 от коммита 0. В каждую из веток добавить по 2-3 коммита, изменяющих один файл.
    Объединить ветки при помощи git merge. Посмотреть, как выглядит история при помощи команды `git logg`.
    Повторить Шаг 1
    Объединить ветки при помощи `git rebase`. Посмотреть, как выглядит история при помощи команды `git logg`. Обратить внимание на изменение хешей коммитов при rebase

    ### Случай 2: Чистая история при помощи `squash`

    С одной стороны - желательно комитить почаще, чтобы не потерять работу. с другой стороны, в конце хочется иметь чистую и понятную историю, где каждый коммит представляет собой завершенный кусок работы, а не бесконечные "fix", "fixed fix" etc. Например, если вы работаете над несколькими файлами одновременно и коммитите изменения в каждый из них в случайном порядке, но хотим, чтобы в результате на изменение одного файла приходился только один коммит. Выход - сквош
    Для этого нужно познакомиться с другим применением git rebase: пересаживать коммиты можно не только на другую ветку, но и на предыдущий коммит в той же ветке. Какая от этого польза? Так как коммиты "накатываются" один за одним, в процессе мы можем их редактировать. Например, изменять commit message, менять коммиты местами или объединять несколько коммитов в один. Последний случай - это и есть squash.

    Упражнение:
    Исходной положение: мы на коммите 0
    внести изменение в файл А, сделать коммит 1
    Внести изменение в файл Б, сделать коммит 2
    Снов изменить файл А, сделать коммит 3
    Задача: при помощи git rebase исправить историю таким образом, чтобы было два коммита - один, меняющий файл А, и один, меняющий файл Б. Для этого нужно заребейсить три последних коммита на коммит 0 интерактивно, при этом поменяв местами коммиты 1 и 3 и засквошив их.
    Исходной положение: мы на коммите 0
    1. Внести любое изменение в файл А, сделать коммит 1
    2. Внести любое изменение в файл Б, сделать коммит 2
    3. Снова изменить файл А, сделать коммит 3
    4. При помощи `git rebase` исправить историю таким образом, чтобы было два коммита - один, меняющий файл А, и один, меняющий файл Б. Для этого нужно заребейсить три последних коммита на коммит 0 интерактивно, при этом поменяв местами коммиты 1 и 3 и "засквошив" их.


    Важные замечания:
  3. @AMashoshyna AMashoshyna created this gist Jan 26, 2020.
    47 changes: 47 additions & 0 deletions Kottans Git Workshop.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    ## `git rebase`

    В общем случае команда `git rebase` добавляет все коммиты из ветки, на которой вы находитесь, следующими за коммитом, который вы передаете `git rebase` как аргумент. Если передать первым аргументом ветку, Git найдет последний общий коммит между текущей веткой и целевой веткой и добавит коммиты из текущей у целевую один за одним. Можно представить себе, что `git rebase` по очереди "накатывает" каждый из коммитов вашей ветки на целевой коммит. При этом у всех "накатанных" коммитов изменяются метаданные (например, родительский коммит), поэтому с точки зрения Git это теперь новые коммиты.

    На семинаре мы познакомились с двумя случаями применения `git rebase`.

    ### Случай 1: объединение веток, `git rebase` как альтернатива `git merge`

    Для того, чтобы объединить две ветки в одну (например, когда работа над задачей закончена и нужно влить это задачу в ветку `master`), часто используют команду `git merge`. Это команда объединяет ветки путем создания отдельного коммита, у которого два родителя - коммиты-вершины каждой из веток на момент слияния.
    Иногда команда `git merge` вызывается неявно. Например, это может произойти при вызове команды `git pull`. Если гит не сможет добавить новые изменения по стратегии fast-forward, создастся merge commit. Мерж-коммиты делают гит-историю нелинейной и плохо управляемой. Проблемы объединения веток при помощи `git merge`:
    - с историей тяжело работать из-за обилия мерж-коммитов (трудно разобраться)
    - может быть трудно взять нужные коммиты в отдельную ветку при помощи cherry-pick, так как они будут зависеть от предыдущих

    Примечание. Избежать нежелательного мерж-коммита при затягивании обновлений можно, если использовать git pull с флагом `--ff-only`.

    `git rebase` избавляет от нежелательных мерж-коммитов, так как он не меняет целевую ветку, а коммиты из текущей ветки добавляет один за одним. Таким образом, ветки не смешиваются, мерж-коммита нет, а ваша работа оказывается в самом верху целевой ветки.

    Дополнительно:
    Гит присваивает коммитам хеши и различает коммиты по хешам. Рекомендуем почитать о том, как работют хеш-функции (на семинаре эта тема не рассматривалась)

    Упражнение
    Исходное положение: коммит 0
    Шаг 1. Создать ветки feat-1 и feat-2 от коммита 0. В каждую из веток добавить по 2-3 коммита, изменяющих один файл.
    Объединить ветки при помощи git merge. Посмотреть, как выглядит история при помощи команды `git logg`.
    Повторить шаг 1
    Объединить ветки при помощи `git rebase`. Посмотреть, как выглядит история при помощи команды `git logg`. Обратить внимание на изменение хешей коммитов при rebase

    ### Случай 2: Чистая история при помощи `squash`

    С одной стороны - желательно комитить почаще, чтобы не потерять работу. с другой стороны, в конце хочется иметь чистую и понятную историю, где каждый коммит представляет собой завершенный кусок работы, а не бесконечные "fix", "fixed fix" etc. Например, если вы работаете над несколькими файлами одновременно и коммитите изменения в каждый из них в случайном порядке, но хотим, чтобы в результате на изменение одного файла приходился только один коммит. Выход - сквош
    Для этого нужно познакомиться с другим применением git rebase: пересаживать коммиты можно не только на другую ветку, но и на предыдущий коммит в той же ветке. Какая от этого польза? Так как коммиты "накатываются" один за одним, в процессе мы можем их редактировать. Например, изменять commit message, менять коммиты местами или объединять несколько коммитов в один. Последний случай - это и есть squash.
    Упражнение:
    Исходной положение: мы на коммите 0
    внести изменение в файл А, сделать коммит 1
    Внести изменение в файл Б, сделать коммит 2
    Снов изменить файл А, сделать коммит 3
    Задача: при помощи git rebase исправить историю таким образом, чтобы было два коммита - один, меняющий файл А, и один, меняющий файл Б. Для этого нужно заребейсить три последних коммита на коммит 0 интерактивно, при этом поменяв местами коммиты 1 и 3 и засквошив их.


    Важные замечания:
    1. Так как `git rebase` меняет коммиты, которые он добавляет в указанное место, нужно быть очень осторожным при rebase коммитов, которые уже отправлены на сервер. Ребейсить коммиты в общих ветках нельзя!
    2. Если в процессе `git rebase` возникает конфликт, `git rebase` останавливается, создает маркеры конфликта в файле (<<<<<<<<) и ждет, пока вы решите конфликт и явно продолжите процесс при помощи `git rebase --continue`. Отдельный коммит (как при мерже) для разрешения конфликта не создается (это еще один плюс `git rebase`)

    ## Git в распределенной команде

    Стратегии Git (например, ГитФлоу) позволяют дают готовое решение для разделения и изоляции работу таким образом, чтобы отдельные команды (или люди) работающие на проектом, не мешали друг другу. Например, тестировщики и разработчики не мешают друг другу.
    Как правило, разработчик создает для своей задачи отдельную ветку от ветки master, делает задачу и вливает свою ветку в master через пул-реквест. В зависимости от проекта и выбранной стратегии промежуточных этапов между завершением работы над задачей и попаданием кода в master может быть несколько - бывают отдельные ветки dev, qa, stage (названия примерные). Каждая такая ветка может быть залита (задеплоена) на отдельную машину, где часть команды (разработчики, тестировщики, продакт-оунер) может протестировать код.