Скотт Чакон - Pro Git
- Название:Pro Git
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Скотт Чакон - Pro Git краткое содержание
В книге рассматриваются следующие темы: основы Git;
ветвление в Git;
Git на сервере;
распределённый Git;
GitHub;
инструменты Git;
настройка Git;
Git и другие системы контроля версий.
Pro Git - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Давайте испробуем как это работает, возьмем существующий репозиторий и разобьем его на два – один со свежими правками, а другой с историческими, и затем посмотрим как мы можем воссоединить их с помощью операции replace, не изменяя при этом значений SHA-1 в свежем репозитории.
Мы будем использовать простой репозиторий с пятью коммитами:
$git log --oneline
ef989d8 fifth commit
c6e1e95 fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit
Мы хотим разбить его на два семейства историй. Одно семейство, которое начинается от первого коммита и заканчивается четвертым, будет историческим. Второе, состоящее пока только из четвертого и пятого коммитов – будет семейством со свежей историей.
Создать историческое семейство легко, мы просто создаем ветку с вершиной на нужном коммите и затем отправляем эту ветку как master в новый удаленный репозиторий.
$git branch history c6e1e95
$git log --oneline --decorate
ef989d8 (HEAD, master) fifth commit
c6e1e95 (history) fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit
Теперь мы можем отправить только что созданную ветвь history в ветку master нашего нового репозитория:
$git remote add project-history https://github.com/schacon/project-history
$git push project-history history:master
Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (12/12), 907 bytes, done.
Total 12 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (12/12), done.
To git@github.com:schacon/project-history.git
* [new branch] history -> master
Таким образом, наша история опубликована, а мы теперь займемся более сложной частью – усечем свежую историю. Нам необходимо перекрытие, так чтобы мы смогли заменить коммит из одной части коммитом из другой, то есть мы будем обрезать историю, оставив четвертый и пятый коммиты (таким образом четвертый коммит будет входить в пересечение).
$git log --oneline --decorate
ef989d8 (HEAD, master) fifth commit
c6e1e95 (history) fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit
В данном случае будет полезным создать базовый коммит, содержащий инструкции о том как раскрыть историю, так другие разработчики будут знать что делать, если они столкнулись с первым коммитом урезанной истории и нуждаются в остальной истории. Итак, далее мы создадим объект заглавного коммита, представляющий нашу отправную точку с инструкциями, а затем перебазируем оставшиеся коммиты (четвертый и пятый) на этот коммит.
Для того, чтобы сделать это, нам нужно выбрать точку разбиения, которой для нас будет третий коммит, хеш которого 9c68fdc. Таким образом, наш базовый коммит будет основываться на этом дереве. Мы можем создать наш базовый коммит, используя команду commit-tree, которая просто берет дерево и возвращает SHA-1 объекта, представляющего новый сиротский коммит.
$echo 'get history from blah blah blah' | git commit-tree 9c68fdc^{tree}
622e88e9cbfbacfb75b5279245b9fb38dfea10cf
Команда commit-tree входит в набор команд, которые обычно называются сантехническими . Это команды, которые обычно не предназначены для непосредственного использования, но вместо этого используются другимикомандами Git для выполнения небольших задач. Периодически, когда мы занимаемся странными задачами подобными текущей, эти команды позволяют нам делать низкоуровневые вещи, но все они не предназначены для повседневного использования. Вы можете прочитать больше о сантехнических командах в Сантехника и Фарфор.
Хорошо. Теперь когда у нас есть базовый коммит, мы можем перебазировать нашу оставшуюся историю на этот коммит используя git rebase --onto. Значением аргумента --onto будет SHA-1 хеш коммита, который мы только что получили от команды commit-tree, а перебазируемой точкой будет третий коммит (родитель первого коммита, который мы хотим сохранить, 9c68fdc):
$git rebase --onto 622e88 9c68fdc
First, rewinding head to replay your work on top of it...
Applying: fourth commit
Applying: fifth commit
Таким образом, мы переписали нашу свежую историю поверх вспомогательного базового коммита, который теперь содержит инструкции о том, как при необходимости восстановить полную историю. Мы можем отправить эту историю в новый проект и теперь, когда люди клонируют его репозиторий, они будут видеть только два свежих коммита и после них базовый коммит с инструкциями.
Давайте представим себя на месте кого-то, кто впервые склонировал проект и хочет получить полную историю. Для получения исторических данных после клонирования усеченного репозитория, ему нужно добавить в список удаленных репозиториев исторический репозиторий и извлечь из него данные:
$git clone https://github.com/schacon/project
$cd project
$git log --oneline master
e146b5f fifth commit
81a708d fourth commit
622e88e get history from blah blah blah
$git remote add project-history https://github.com/schacon/project-history
$git fetch project-history
From https://github.com/schacon/project-history
* [new branch] master -> project-history/master
Теперь у этого пользователя его собственные свежие коммиты будут находиться в ветке master, а исторические коммиты в ветке project-history/master.
$git log --oneline master
e146b5f fifth commit
81a708d fourth commit
622e88e get history from blah blah blah
$git log --oneline project-history/master
c6e1e95 fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit
Для объединения этих веток вы можете просто вызывать git replace, указав коммит, который вы хотите заменить, и коммит, которым вы хотите заменить первый. Так мы хотим заменить "четвертый" коммит в основной ветке "четвертым" коммитом из ветки project-history/master:
$git replace 81a708d c6e1e95
Если теперь вы посмотрите историю ветки master, то должны увидеть нечто подобное:
$git log --oneline master
e146b5f fifth commit
81a708d fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit
Здорово, не правда ли? Не изменяя SHA-1 всех коммитов семейства, мы можем заменить один коммит в нашей истории совершенно другим коммитом и все обычные утилиты (bisect, blame и т.д.) будут работать как от них это и ожидается.
Интересно, что для четвертого коммита SHA-1 хеш выводится равной 81a708d, хотя в действительности он содержит данные коммита c6e1e95, которым мы его заменили. Даже если вы выполните команду типа cat-file, она отобразит замененные данные:
$git cat-file -p 81a708d
tree 7bc544cf438903b65ca9104a1e30345eee6c083d
parent 9c68fdceee073230f19ebb8b5e7fc71b479c0252
author Scott Chacon 1268712581 -0700
Читать дальшеИнтервал:
Закладка: