- 3.2 Ветвление в Git — Основы ветвления и слияния
- Основы ветвления и слияния
- Основы ветвления
- Основы слияния
- Основные конфликты слияния
- Git: распространённые ошибки и способы их исправления
- Ошибка в сообщении последнего коммита
- Ошибка в имени ветки
- Случайный коммит изменений в ветку master
- Работа с файлами, которые забыли добавить в последний коммит
- Добавление не того файла в репозиторий
- Что делать, если всё пошло не так?
- Итоги
- Git happens! 6 типичных ошибок Git и как их исправить
- 1. Упс… Я ошибся в сообщении к последнему коммиту
- 2. Упс… Я забыл добавить файл к последнему коммиту
- 3. Упс… Я добавил файл, который не должен быть в этом репозитории
- 4. Упс… Я коммитнул изменения в master
- 5. Упс… Я сделал ошибку в названии ветки
- 6. Oops… I did it again!
- Бонус от переводчика
3.2 Ветвление в Git — Основы ветвления и слияния
Основы ветвления и слияния
Давайте рассмотрим простой пример рабочего процесса, который может быть полезен в вашем проекте. Ваша работа построена так:
Вы работаете над сайтом.
Вы создаете ветку для новой статьи, которую вы пишете.
Вы работаете в этой ветке.
В этот момент вы получаете сообщение, что обнаружена критическая ошибка, требующая скорейшего исправления. Ваши действия:
Переключиться на основную ветку.
Создать ветку для добавления исправления.
После тестирования слить ветку содержащую исправление с основной веткой.
Переключиться назад в ту ветку, где вы пишете статью и продолжить работать.
Основы ветвления
Предположим, вы работаете над проектом и уже имеете несколько коммитов.
Вы решаете, что теперь вы будете заниматься проблемой #53 из вашей системы отслеживания ошибок. Чтобы создать ветку и сразу переключиться на нее, можно выполнить команду git checkout с параметром -b :
Это то же самое что и:
Вы работаете над своим сайтом и делаете коммиты. Это приводит к тому, что ветка iss53 движется вперед, так как вы переключились на нее ранее ( HEAD указывает на нее).
Тут вы получаете сообщение об обнаружении уязвимости на вашем сайте, которую нужно немедленно устранить. Благодаря Git, не требуется размещать это исправление вместе с тем, что вы сделали в iss53 . Вам даже не придется прилагать усилий, чтобы откатить все эти изменения для начала работы над исправлением. Все, что вам нужно — переключиться на ветку master .
Но перед тем как сделать это — имейте в виду, что если рабочий каталог либо индекс содержат незафиксированные изменения, конфликтующие с веткой, на которую вы хотите переключиться, то Git не позволит переключить ветки. Лучше всего переключаться из чистого рабочего состояния проекта. Есть способы обойти это (припрятать изменения (stash) или добавить их в последний коммит (amend)), но об этом мы поговорим позже в разделе Припрятывание и очистка главы 7. Теперь предположим, что вы зафиксировали все свои изменения и можете переключиться на ветку master :
С этого момента ваш рабочий каталог имеет точно такой же вид, какой был перед началом работы над проблемой #53, и вы можете сосредоточиться на работе над исправлением. Важно запомнить: когда вы переключаете ветки, Git возвращает состояние рабочего каталога к тому виду, какой он имел в момент последнего коммита в эту ветку. Он добавляет, удаляет и изменяет файлы автоматически, чтобы состояние рабочего каталога соответствовало тому, когда был сделан последний коммит.
Теперь вы можете перейти к написанию исправления. Давайте создадим новую ветку для исправления, в которой будем работать, пока не закончим исправление.
Вы можете прогнать тесты, чтобы убедиться, что ваше исправление делает именно то, что нужно. И если это так — выполнить слияние ветки hotfix с веткой master для включения изменений в продукт. Это делается командой git merge :
Заметили фразу «fast-forward» в этом слиянии? Git просто переместил указатель ветки вперед, потому что коммит C4 , на который указывает слитая ветка hotfix , был прямым потомком коммита C2 , на котором вы находились до этого. Другими словами, если коммит сливается с тем, до которого можно добраться двигаясь по истории прямо, Git упрощает слияние просто перенося указатель ветки вперед, так как нет расхождений в изменениях. Это называется «fast-forward».
Теперь ваши изменения включены в коммит, на который указывает ветка master , и исправление можно внедрять.
После внедрения вашего архиважного исправления, вы готовы вернуться к работе над тем, что были вынуждены отложить. Но сначала нужно удалить ветку hotfix , потому что она больше не нужна — ветка master указывает на то же самое место. Для удаления ветки выполните команду git branch с параметром -d :
Теперь вы можете переключиться обратно на ветку iss53 и продолжить работу над проблемой #53:
Стоит обратить внимание на то, что все изменения из ветки hotfix не включены в вашу ветку iss53 . Если их нужно включить, вы можете влить ветку master в вашу ветку iss53 командой git merge master , или же вы можете отложить слияние этих изменений до завершения работы, и затем влить ветку iss53 в master .
Основы слияния
Предположим, вы решили, что работа по проблеме #53 закончена и её можно влить в ветку master . Для этого нужно выполнить слияние ветки iss53 точно так же, как вы делали это с веткой hotfix ранее. Все, что нужно сделать — переключиться на ветку, в которую вы хотите включить изменения, и выполнить команду git merge :
Результат этой операции отличается от результата слияния ветки hotfix . В данном случае процесс разработки ответвился в более ранней точке. Так как коммит, на котором мы находимся, не является прямым родителем ветки, с которой мы выполняем слияние, Git придётся немного потрудиться. В этом случае Git выполняет простое трёхстороннее слияние, используя последние коммиты объединяемых веток и общего для них родительского коммита.
Вместо того, чтобы просто передвинуть указатель ветки вперёд, Git создаёт новый результирующий снимок трёхстороннего слияния, а затем автоматически делает коммит. Этот особый коммит называют коммитом слияния, так как у него более одного предка.
Теперь, когда изменения слиты, ветка iss53 больше не нужна. Вы можете закрыть задачу в системе отслеживания ошибок и удалить ветку:
Основные конфликты слияния
Иногда процесс не проходит гладко. Если вы изменили одну и ту же часть одного и того же файла по-разному в двух объединяемых ветках, Git не сможет их чисто объединить. Если ваше исправление ошибки #53 потребовало изменить ту же часть файла что и hotfix , вы получите примерно такое сообщение о конфликте слияния:
Git не создал коммит слияния автоматически. Он остановил процесс до тех пор, пока вы не разрешите конфликт. Чтобы в любой момент после появления конфликта увидеть, какие файлы не объединены, вы можете запустить git status :
Всё, где есть неразрешённые конфликты слияния, перечисляется как неслитое. В конфликтующие файлы Git добавляет специальные маркеры конфликтов, чтобы вы могли исправить их вручную. В вашем файле появился раздел, выглядящий примерно так:
Это означает, что версия из HEAD (вашей ветки master , поскольку именно её вы извлекли перед запуском команды слияния) — это верхняя часть блока (всё, что над ======= ), а версия из вашей ветки iss53 представлена в нижней части. Чтобы разрешить конфликт, придётся выбрать один из вариантов, либо объединить содержимое по-своему. Например, вы можете разрешить конфликт, заменив весь блок следующим:
В этом разрешении есть немного от каждой части, а строки , ======= и >>>>>>> полностью удалены. Разрешив каждый конфликт во всех файлах, запустите git add для каждого файла, чтобы отметить конфликт как решённый. Добавление файла в индекс означает для Git, что все конфликты в нём исправлены.
Если вы хотите использовать графический инструмент для разрешения конфликтов, можно запустить git mergetool , который проведет вас по всем конфликтам:
Если вы хотите использовать инструмент слияния не по умолчанию (в данном случае Git выбрал opendiff , поскольку команда запускалась на Mac), список всех поддерживаемых инструментов представлен вверху после фразы «one of the following tools». Просто введите название инструмента, который хотите использовать.
Мы рассмотрим более продвинутые инструменты для разрешения сложных конфликтов слияния в разделе Продвинутое слияние главы 7.
После выхода из инструмента слияния Git спросит об успешности процесса. Если вы ответите скрипту утвердительно, то он добавит файл в индекс, чтобы отметить его как разрешенный. Теперь можно снова запустить git status , чтобы убедиться в отсутствии конфликтов:
Если это вас устраивает и вы убедились, что все файлы, где были конфликты, добавлены в индекс — выполните команду git commit для создания коммита слияния. Комментарий к коммиту слияния по умолчанию выглядит примерно так:
Если вы считаете, что коммит слияния требует дополнительных пояснений — опишите как были разрешены конфликты и почему были применены именно такие изменения, если это не очевидно.
Источник
Git: распространённые ошибки и способы их исправления
Если вы когда-нибудь работали над большим проектом, в котором, помимо вас, участвуют и многие другие программисты, тогда вы, очевидно, применяли Git в роли системы контроля версий. В ходе использования чего-то, по уровню сложности похожего Git, все совершают ошибки.
Ошибка в сообщении последнего коммита
После нескольких часов хорошей работы легко допустить ошибку в сообщении коммита. К счастью, это легко исправить с помощью следующей команды:
Эта команда откроет редактор и позволит внести изменения в последнее сообщение коммита. Никому кроме вас не стоит знать, что вы написали «Initial commment» с тремя «m».
Ошибка в имени ветки
Предположим, что на часах почти 15:00, а вы ещё не обедали. В результате, терзаемые голодом, вы назвали новую ветку feature-brunch . Вкуснятина, ничего не скажешь.
Эту проблему тоже можно решить. Переименовать ветку можно так же, как переименовывают файлы с помощью команды mv . Речь идёт о перемещении её в новое место с правильным именем:
Если вы уже отправили эту ветку в репозиторий, вам, для её переименования, потребуется сделать ещё пару дел. Старую ветку надо удалить, а новую — отправить в репозиторий:
Случайный коммит изменений в ветку master
Предположим, вы работаете над некоей новой возможностью, и, в спешке, забыли создать для неё новую ветку. Вы закоммитили уже кучу файлов и всё это лежит в ветке master . Переместить все эти изменения в новую ветку можно с помощью следующих трёх команд. Обратите внимание на то, что если вы не воспользовались, в применении к изменениям, командами commit или stash , они будут утеряны.
В результате будет создана новая ветка, будет произведён откат изменений в ветке master , до состояния, в котором она была до внесения изменений, и будет осуществлён переход в новую ветку, которая будет содержать в себе все изменения, внесённые ранее в master .
Работа с файлами, которые забыли добавить в последний коммит
Ещё одна распространённая оплошность при работе с Git заключается в том, что коммиты делают слишком рано и в них не попадают нужные файлы. Скажем, вы пропустили некий файл, забыли его сохранить, или вам нужно внести небольшое изменение в файл для того, чтобы последний коммит имел смысл. В подобной ситуации вам снова пригодится команда —amend . Добавьте пропущенный файл в индекс репозитория и запустите эту команду:
После этого вы можете изменить сообщение коммита, либо оставить его таким же, каким оно было.
Добавление не того файла в репозиторий
Как быть, если ваша ошибка представляет собой полную противоположность предыдущей? Что если вы добавили в индекс файл, который не собираетесь коммитить? Это может быть какой-нибудь ENV-файл, директория сборки проекта, фото вашей собаки, которое вы случайно сохранили не в той папке. Всё это можно исправить.
Если ваши действия ограничиваются индексированием файла, но вы пока не закоммитили его, справиться с проблемой будет очень легко, воспользовавшись командой reset :
Если вы продвинулись достаточно далеко и успели изменение закоммитить, то знайте, что и это поправимо. Придётся лишь воспользоваться ещё несколькими командами:
В результате последний коммит будет отменён, изображение будет удалено, после чего новый коммит будет помещён туда, где ему положено быть.
Что делать, если всё пошло не так?
Методика, которую мы сейчас обсудим, помогает в ситуациях, когда всё идёт не так, как надо. Например, такое происходит, когда вы слишком увлекаетесь копированием готовых решений со StackOverflow, и, после работы, ваш репозиторий оказывается в худшем состоянии чем он был в самом начале. В такую ситуацию, пожалуй, попадали все мы.
Команда git reflog показывает список всего, что вы сделали. Затем она позволяет воспользоваться инструментами Git для отката изменений, для возврата к одному из прошлых состояний репозитория. Стоит отметить, что этот метод стоит рассматривать как последнее средство, и, прежде чем им воспользоваться, стоит как следует подумать. Итак, вывести список того, что было сделано, можно следующей командой:
Git помнит все наши действия и в результате выполнения этой команд можно увидеть примерно следующее:
Обратите внимание на самую левую колонку этого списка. Тут содержатся индексы. Если вам нужно вернуться назад, в некий момент прошлого, выполните следующую команду, заменив
Итоги
Мы рассмотрели некоторые способы борьбы с ошибками, возникающими при работе с Git. Надеемся, вы подобных ошибок не допустите и вам эти приёмы работы с Git не пригодятся. А если что-то пойдёт не так — вы будете знать, что делать.
Уважаемые читатели! Знаете о каких-нибудь интересных приёмах работы с Git? Если так — просим ими поделиться.
Источник
Git happens! 6 типичных ошибок Git и как их исправить
Прим. перев.: На днях в блоге для инженеров любимого нами проекта GitLab появилась небольшая, но весьма полезная заметка с инструкциями, которые помогают сохранить время и нервы в случае различных проблем, случающихся по мере работы с Git. Вряд ли они будут новы для опытных пользователей, но обязательно найдутся и те, кому они пригодятся. А в конец этого материала мы добавили небольшой бонус от себя. Хорошей всем пятницы!
Все мы делаем ошибки, особенно при работе с такими сложными системами, как Git. Но помните: Git happens!
Если вы только начинаете путь с Git, обучитесь основам работы с ним в командной строке. А здесь я расскажу о том, как можно исправить шесть наиболее распространённых ошибок в Git.
1. Упс… Я ошибся в сообщении к последнему коммиту
После нескольких часов кодинга легко допустить ошибку в сообщении коммита. К счастью, это легко исправить:
С этой командой откроется текстовый редактор и позволит внести изменения в сообщение к последнему коммиту. И никто не узнает, что вы написали «addded» с тремя «d».
2. Упс… Я забыл добавить файл к последнему коммиту
Другая популярная ошибка в Git — слишком поспешный коммит. Вы забыли добавить файл, забыли его сохранить или должны внести небольшое изменение, чтобы коммит стал осмысленным? Вашим другом снова будет —amend .
Добавьте недостающий файл и выполните эту верную команду:
Теперь вы можете либо откорректировать сообщение, либо просто сохранить его в прежнем виде (с добавленным файлом).
3. Упс… Я добавил файл, который не должен быть в этом репозитории
Но что, если у вас обратная ситуация? Что, если вы добавили файл, который не хотите коммитить? Обманчивый ENV-файл, директорию сборки или фото с котом, что было случайно сохранено в неправильном каталоге… Всё решаемо.
Если вы сделали только stage для файла и ещё не коммитнули его, всё делается через простой reset нужного файла (находящегося в stage):
Если же вы всё-таки коммитнули изменение, потребуется дополнительный предварительный шаг:
Коммит будет откачен, картинка удалена, а затем сделан новый коммит.
Прим. перев.: Как замечено в комментариях к оригинальной статье, эту проблему тоже можно решить с помощью уже упомянутого —amend . По всей видимости, данным пунктом автор хотел показать, какие ещё есть способы изменения истории коммитов для исправления ошибки.
4. Упс… Я коммитнул изменения в master
Итак, вы работаете над новой фичей и поспешили, забыв создать новую ветку для неё. Вы уже коммитнули кучу файлов и все эти коммиты оказались в master’е. К счастью, GitLab может предотвращать push’ы прямо в master. Поэтому мы можем откатить все нужные изменения в новую ветку следующими тремя командами:
Примечание: Убедитесь, что сначала коммитнули или stash‘нули свои изменения — иначе все они будут утеряны!
Будет создана новая ветка, в master’е — произведён откат до состояния, в котором он был до ваших изменений, а затем сделан checkout новой ветки со всеми вашими изменениями.
5. Упс… Я сделал ошибку в названии ветки
Самые внимательные могли заметить в предыдущем примере ошибку в названии ветки. Уже почти 15:00, а я всё ещё не обедал, поэтому мой голод назвал новую ветку (branch) как future-brunch. Вкуснотища!
Переименуем эту ветку аналогичным способом, что используется при переименовании файла с помощью команды mv, то есть поместив её в новое место с правильным названием:
Если вы уже push’нули эту ветку, понадобится пара дополнительных шагов. Мы удалим старую ветку из remote и push’нем новую:
Прим. перев.: Удалить ветку из remote ещё можно с помощью:
6. Oops… I did it again!
Последняя команда на тот случай, когда всё пошло не так. Когда вы накопировали и навставляли кучу решений со Stack Overflow, после чего в репозитории всё стало ещё хуже, чем было в начале. Все мы однажды сталкивались с подобным…
git reflog показывает список всех выполненных вами операций. Затем он позволяет использовать магические возможности Git’а по путешествию во времени, т.е. вернуться к любому моменту из прошлого. Должен отметить, что это ваша последняя надежда — не стоит прибегать к ней в простых случаях. Итак, чтобы получить список, выполните:
Каждый наш шаг находится под чутким наблюдением Git’а. Запуск команды на проекте выше выдал следующее:
Обратите внимание на самый левый столбец — это индекс. Если вы хотите вернуться к любому моменту в истории, выполните следующую команду, заменив
Итак, теперь у вас есть шесть способов выбраться из самых частых Gitfalls (игра слов: pitfall переводится как «ловушка, ошибка» — прим. перев.).
Бонус от переводчика
Во-первых, ценное замечание ко всему написанному выше (кроме пункта 5). Нужно учитывать, что эти действия меняют историю коммитов, поэтому их следует проводить, только если изменения не были отправлены в remote (push’нуты). В противном случае старый плохой коммит уже будет на remote-ветке и придётся либо выполнять git pull (который сделает merge, и тогда попытка «почистить» историю приведёт к худшим последствиям), либо git push —force , что чревато потерей данных при работе с веткой нескольких человек…
Теперь — небольшие полезные дополнения из нашего опыта:
- Если вы (случайно или нет) сменили ветку и вам нужно вернуться на предыдущую, самый быстрый способ — использовать git checkout — .
- Если вы случайно добавили к коммиту файл, который не должен быть туда добавлен, но ещё не сделали коммит — используйте git reset HEAD path/to/file . Похожая ситуация описана в пункте 3, но в действительности она шире, т.к. относится к любым ненужным изменениям в коммите (не только к случаю лишнего файла).
- Хорошей практикой, чтобы не закоммитить лишнего, является использование параметра -p при добавлении файла к коммиту ( git add -p ). Это позволяет сделать review каждого изменения, которое уйдёт в коммит. Но стоит помнить, что он не добавляет к коммиту untracked-файлы — их нужно добавлять без этого параметра.
- Ряд хороших рекомендаций (в том числе и более сложных), можно найти в статье 2014 года «Git Tutorial: 10 Common Git Problems and How to Fix Them». В частности, обратите внимание на использование git revert и git rebase -i .
Источник