Скотт Чакон - Pro Git
- Название:Pro Git
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Скотт Чакон - Pro Git краткое содержание
В книге рассматриваются следующие темы: основы Git;
ветвление в Git;
Git на сервере;
распределённый Git;
GitHub;
инструменты Git;
настройка Git;
Git и другие системы контроля версий.
Pro Git - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Такую же информацию вы можете получить и после выполнения слияния с помощью команды git log, узнав таким образом как был разрешен конфликт. Git выводит информацию в таком формате, если вы выполните git show для коммита слияния или вызовете команду git log -p с опцией ‘--cc’ (без нее данная команда не показывает изменения для коммитов слияния).
$git log --cc -p -1
commit 14f41939956d80b9e17bb8721354c33f8d5b5a79
Merge: f1270f7 e3eb223
Author: Scott Chacon
Date: Fri Sep 19 18:14:49 2014 +0200
Merge branch 'mundo'
Conflicts:
hello.rb
diff --cc hello.rb
index 0399cd5,59727f0..e1d0799
--- a/hello.rb
+++ b/hello.rb
@@@ -1,7 -1,7 +1,7 @@@
#! /usr/bin/env ruby
def hello
- puts 'hola world'
- puts 'hello mundo'
++ puts 'hola mundo'
end
hello()
Отмена слияний
Теперь когда вы знаете как создать коммит слияния, вы можете сделать ее по ошибке. Одна из замечательных вещей в работе с Git – это то, что ошибки совершать не страшно, так как есть возможность исправить их (и в большинстве случаев сделать это просто).
Коммит слияния не исключение. Допустим, вы начали работать в тематической ветке, случайно слили ее в master, и теперь ваша история коммитов выглядит следующим образом:
Рисунок 2. Случайный коммит слияния
Есть два подхода к решению этой проблемы, в зависимости от того, какой результат вы хотите получить.
Исправление ссылок
Если нежелаемый коммит слияния существует только в вашем локальном репозитории, то простейшее и лучшее решение состоит в перемещении веток так, чтобы они указывали туда куда вам нужно. В большинстве случаев, если вы после случайного git merge выполните команду git reset --hard HEAD~, то указатели веток восстановятся так, что будут выглядеть следующим образом:
Рисунок 3. История после git reset --hard HEAD~
Мы рассматривали команду reset ранее в Раскрытие тайн reset, поэтому вам должно быть не сложно разобраться с тем, что здесь происходит. Здесь небольшое напоминание: reset --hard обычно выполняет три шага:
1. Перемещает ветку, на которую указывает HEAD. В данном случае мы хотим переместить master туда, где она была до коммита слияния (C6).
2. Приводит индекс к такому же виду что и HEAD.
3. Приводит рабочую директорию к такому же виду, что и индекс.
Недостаток этого подхода состоит в изменении истории, что может привести к проблемам в случае совместно используемого репозитория. Загляните в Опасности перемещения, чтобы узнать что именно может произойти; кратко говоря, если у других людей уже есть какие-то из изменяемых вами коммитов, вы должны отказаться от использования reset. Этот подход также не будет работать, если после слияния уже был сделан хотя бы один коммит; перемещение ссылки фактически приведет к потере этих изменений.
Отмена коммита
Если перемещение указателей ветки вам не подходит, Git предоставляет возможность сделать новый коммит, которая откатывает все изменения, сделанные в другой. Git называет эту операцию “восстановлением” (“revert”), в данном примере вы можете вызвать ее следующим образом:
$git revert -m 1 HEAD
[master b1d8379] Revert "Merge branch 'topic'"
Опция -m 1 указывает какой родитель является “основной веткой” и должен быть сохранен. Когда вы выполняете слияние в HEAD (git merge topic), новый коммит будет иметь двух родителей: первый из них HEAD (C6), а второй – вершина ветки, которую сливают с текущей (C4). В данном случае, мы хотим отменить все изменения, внесенные слиянием родителя #2 (C4), и сохранить при этом всё содержимое из родителя #1 (C6).
История с коммитом восстановления (отменой коммита слияния) выглядит следующим образом:
Рисунок 4. Итория после git revert -m 1
Новый коммит ^M имеет точно такое же содержимое как C6, таким образом, начиная с нее всё выглядит так, как будто слияние никогда не выполнялось, за тем лишь исключением, что “теперь уже не слитые” коммиты всё также присутствуют в истории HEAD. Git придет в замешательство, если вы вновь попытаетесь слить topic в ветку master:
$git merge topic
Already up-to-date.
В ветке topic нет ничего, что еще недоступно из ветки master. Плохо, что в случае добавления новых наработок в topic, при повторении слияния Git добавит только те изменения, которые были сделаны после отмены слияния:
Рисунок 5. История с плохим слиянием
Лучшим решением данной проблемы является откат коммита отмены слияния, так как теперь вы хотите внести изменения, которые были отменены, а затемсоздание нового коммита слияния:
$git revert ^M
[master 09f0126] Revert "Revert "Merge branch 'topic'""
$git merge topic
Рисунок 6. История после повторения отмененного слияния
В этом примере, M и ^M отменены. В коммите ^^M, фактически, сливаются изменения из C3 и C4, а в C8 – изменения из C7, таким образом, ветка topic полностью слита.
Другие типы слияний
До этого момента мы рассматривали типичные слияния двух веток, которые обычно выполняются с использованием стратегии слияния, называемой “рекурсивной”. Но существуют и другие типы слияния веток. Давайте кратко рассмотрим некоторые из них.
Выбор “нашей” или “их” версий
Во-первых, существует еще один полезный прием, который мы можем использовать в обычном “рекурсивном” режиме слияния. Мы уже видели опции ignore-all-space и ignore-space-change, которые передаются с префиксом -X, но мы можем также попросить Git при возникновении конфликта использовать ту или иную версию файлов.
По умолчанию, когда Git при слиянии веток замечает конфликт, он добавляет в код маркеры конфликта, отмечает файл как конфликтующий и позволяет вам разрешить его. Если же вместо ручного разрешения конфликта вы хотите, чтобы Git просто использовал какую-то определенную версию файла, а другую игнорировал, то вы можете передать команде merge одну из двух опций -Xours или -Xtheirs.
В этом случае Git не будет добавлять маркеры конфликта. Все неконфликтующие изменения он сольет, а для конфликтующих он целиком возьмет ту версию, которую вы указали (это относится и к бинарным файлам).
Если мы вернемся к примеру “hello world”, который использовали раньше, то увидим, что попытка слияния в нашу ветку приведет к конфликту.
$git merge mundo
Читать дальшеИнтервал:
Закладка: