Скотт Чакон - Pro Git
- Название:Pro Git
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Скотт Чакон - Pro Git краткое содержание
В книге рассматриваются следующие темы: основы Git;
ветвление в Git;
Git на сервере;
распределённый Git;
GitHub;
инструменты Git;
настройка Git;
Git и другие системы контроля версий.
Pro Git - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
$git diff-tree -p rack_branch
Для сравнения содержимого вашей субдиректории rack с тем, что находилось в ветке master сервера, когда вы последний раз извлекали из него изменения, вы можете выполнить:
$git diff-tree -p rack_remote/master
Rerere
Функциональность git rerere – частично скрытый компонент Git. Ее имя является сокращением для “reuse recorded resolution” (“повторное использование сохраненных разрешений конфликтов”). Как следует из имени, эта функциональность позволяет попросить Git запомнить то, как вы разрешили некоторую часть конфликта, так что в случае возникновения такого же конфликта, Git сможет его разрешить автоматически.
Существует несколько ситуаций, в которых данная функциональность может быть действительно удобна. Один из примеров, упомянутый в документации, состоит в том, чтобы обеспечить в будущем простоту слияния некоторой долгоживущей ветки, не создавая при этом набор промежуточных коммитов слияния. При использовании rerere вы можете время от времени выполнять слияния, разрешать конфликты, а затем откатывать слияния. Если делать это постоянно, то итоговое слияние должно пройти легко, так как rerere сможет разрешить все конфликты автоматически.
Такая же тактика может быть использована, если вы хотите сохранить ветку легко перебазируемой, то есть вы не хотите сталкиваться с одними и теми же конфликтами каждый раз при перебазировании. Или, например, вы решили ветку, которую уже сливали и разрешали при этом некоторые конфликты, вместо слияния перебазировать – наврядли вы захотите разрешать те же конфликты еще раз.
Другая ситуация возникает, когда вы изредка сливаете несколько веток, относящихся к еще разрабатываемым задачам, в одну тестовую ветку, как это часто делается в проекте самого Git. Если тесты завершатся неудачей, вы можете откатить все слияния и повторить их, исключив из них ветку, которая поломала тесты, при этом не разрешая конфликты снова.
Для того, чтобы включить функциональность rerere, достаточно изменить настройки следующим образом:
$git config --global rerere.enabled true
Также вы можете включить ее, создав каталог .git/rr-cache в нужном репозитории, но включение через настройки понятнее и может быть сделано глобально.
Давайте рассмотрим простой пример, подобный используемому ранее. Предположим, у нас есть файл вида:
#! /usr/bin/env ruby
def hello
puts 'hello world'
end
Как и ранее, в одной ветке мы изменили слово “hello” на “hola”, а в другой – слово “world” на “mundo”.
Когда мы будем сливать эти две ветки в одну, мы получим конфликт:
$git merge i18n-world
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Recorded preimage for 'hello.rb'
Automatic merge failed; fix conflicts and then commit the result.
Вы должно быть заметили в выводе новую строку Recorded preimage for FILE. Во всем остальном вывод такой же, как при обычном конфликте слияния. В этот момент rerere может сообщить нам несколько вещей. Обычно в такой ситуации вы можете выполнить git status, чтобы увидеть в чем заключается конфликт:
$git status
#On branch master
#Unmerged paths:
#(use "git reset HEAD ..." to unstage)
#(use "git add ..." to mark resolution)
#
#both modified: hello.rb
#
Однако, с помощью команды git rerere status вы также можете узнать, для каких файлов git rerere сохранил снимки состояния, в котором они были до начала слияния:
$git rerere status
hello.rb
А команда git rerere diff показывает текущее состояние разрешения конфликта – то, с чего вы начали разрешать конфликт, и то, как вы его разрешили (фактически, патч, который в дальнейшем можно использовать для разрешения такого же конфликта).
$git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,11 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
+<<<<<<< HEAD
puts 'hola world'
->>>>>>>
+=======
+ puts 'hello mundo'
+>>>>>>> i18n-world
end
Также (и это уже не относится к rerere), вы можете использовать команду ls-files -u, чтобы увидеть конфликтующие файлы, их общую родительскую версию и обе сливаемых версии:
$git ls-files -u
100644 39804c942a9c1f2c03dc7c5ebcd7f3e3a6b97519 1 hello.rb
100644 a440db6e8d1fd76ad438a49025a9ad9ce746f581 2 hello.rb
100644 54336ba847c3758ab604876419607e9443848474 3 hello.rb
Теперь вы можете разрешить конфликт, используя puts 'hola mundo', и снова выполнить команду rerere diff, чтобы увидеть, что именно rerere запомнит:
$git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,7 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
- puts 'hola world'
->>>>>>>
+ puts 'hola mundo'
end
То есть, когда Git увидит в файле hello.rb конфликт, в котором с одной строны стоит “hello mundo” и “hola world” с другой, он разрешит его как “hola mundo”.
Теперь мы можем отметить конфликт как разрешенный и закоммитить его:
$git add hello.rb
$git commit
Recorded resolution for 'hello.rb'.
[master 68e16e5] Merge branch 'i18n'
Как вы видите, при этом было "сохранено разрешение конфликта для ФАЙЛА" ("Recorded resolution for FILE").
Теперь давайте отменим это слияние и перебазируем ветку i18n-world поверх master. Как мы видели в Раскрытие тайн reset, мы можем переместить нашу ветку назад, используя команду reset.
$git reset --hard HEAD^
HEAD is now at ad63f15 i18n the hello
Наше слияние отменено. Теперь давайте перебазируем ветку i18n-world.
$git checkout i18n-world
Switched to branch 'i18n-world'
$git rebase master
First, rewinding head to replay your work on top of it...
Applying: i18n one word
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Resolved 'hello.rb' using previous resolution.
Failed to merge in the changes.
Patch failed at 0001 i18n one word
При этом мы получили ожидаемый конфликт слияния, но обратите внимание на строку Resolved FILE using previous resolution. Если мы посмотрим на содержимое файла, то увидим, что конфликт уже был разрешен, и в файле отсутствуют маркеры конфликта слияния.
$cat hello.rb
#! /usr/bin/env ruby
def hello
puts 'hola mundo'
end
При этом команда git diff покажет вам как именно этот конфликт был автоматически повторно разрешен:
$git diff
diff --cc hello.rb
index a440db6,54336ba..0000000
--- 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
С помощью команды checkout вы можете вернуть этот файл назад в конфликтующее состояние:
$git checkout --conflict=merge hello.rb
$cat hello.rb
#! /usr/bin/env ruby
def hello
<<<<<<< ours
puts 'hola world'
=======
puts 'hello mundo'
Читать дальшеИнтервал:
Закладка: