10.5. The Refspec
Это типа конспект, который я веду для себя, чтобы получше разобраться и запомнить. Вероятно, вам лучше сразу читать оригинал: 10.5 The Refspec.
Эээксперименты
Эксперимент 1
Создаём репозиторий и настраиваем копии:
- Делаем две локальные копии одного репозитория
- В одном (local) делаем маппинг веточек с плюсиком: fetch = +refs/heads/::refs/remotes/origin/
- В другом (local2) — без плюсика: fetch = refs/heads/::refs/remotes/origin/
- Накоммитим чего-нибудь в мастер и синхронизируем копии
Делаем не fast-forward пуш из local (с флагом --force)
-
Смотрим, что в local:
$ git log --pretty=oneline --abbrev-commit 9efa81f (HEAD -> master) from local1 dbe85a9 init repo $ cat .git/refs/heads/master 9efa81f6ae9e42e8c731d4f57e2ac31e34f127fd $ cat .git/refs/remotes/origin/master 9efa81f6ae9e42e8c731d4f57e2ac31e34f127fd -
Смотрим, что в remote:
$ git log --pretty=oneline --abbrev-commit 9efa81f (HEAD -> master) from local1 dbe85a9 init repo $ cat refs/heads/master 9efa81f6ae9e42e8c731d4f57e2ac31e34f127fd
Фетч в local2:
-
Как сфетчилось:
$ git fetch From ../remote * [new branch] master -> origin/master serdgos-MBP:local2 chiv$ git fetch remote: Counting objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From ../remote ! [rejected] master -> origin/master (non-fast-forward) -
Смотрим, что получилось:
$ cat .git/refs/remotes/origin/master 447df54caf81a3d4430f87b5e9cd88da9bd9890aТо есть видим, что не сфетчилось.
-
Форсим фетч:
$ git fetch --force From /Volumes/data/chiv/zablots/gitbook/local2/../remote + 447df54...9efa81f master -> origin/master (forced update) $ cat .git/refs/remotes/origin/master 9efa81f6ae9e42e8c731d4f57e2ac31e34f127fd
Делаем не fast-forward пуш из local2 (с флагом --force)
-
Смотрим, что в local2:
$ git log --pretty=oneline --abbrev-commit 447df54 (HEAD -> master, origin/master) from local2 dbe85a9 init repo $ cat .git/refs/heads/master 447df54caf81a3d4430f87b5e9cd88da9bd9890a $ cat .git/refs/remotes/origin/master 447df54caf81a3d4430f87b5e9cd88da9bd9890a -
Смотрим, что в remote:
$ git log --pretty=oneline --abbrev-commit 447df54 (HEAD -> master) from local2 dbe85a9 init repo $ cat refs/heads/master 447df54caf81a3d4430f87b5e9cd88da9bd9890a
Фетч в local:
-
Как сфетчилось:
$ git fetch From ../remote + 9efa81f...447df54 master -> origin/master (forced update) -
Смотрим, что получилось:
$ cat .git/refs/remotes/origin/master 447df54caf81a3d4430f87b5e9cd88da9bd9890aТо есть сфетчилось даже без флага --force
Эксперимент 2
Поэкспериментирует со спеками пуша.
Зададим такую спецификацию в local:
[remote "origin"]
url = ../remote
fetch = +refs/heads/*:refs/remotes/origin/*
push = refs/heads/master:refs/remotes/origin/ololo
Сделаем пуш из local2
-
Смотрим, что в local2:
$ git log --pretty=oneline --abbrev-commit f08ce8a (HEAD -> master, origin/master) from local2 9efa81f from local1 dbe85a9 init repo $ find .git/refs -type f -exec grep -H "" {} \; .git/refs/heads/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3 .git/refs/remotes/origin/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3 -
Смотрим, что в remote:
$ git log --pretty=oneline --abbrev-commit f08ce8a (HEAD -> master) from local2 9efa81f from local1 dbe85a9 init repo $ find refs -type f -exec grep -H "" {} \; refs/heads/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3
Пуллимся в local.
$ git log --pretty=oneline --abbrev-commit
f08ce8a (HEAD -> master, origin/master) from local2
9efa81f from local1
dbe85a9 init repo
$ find .git/refs -type f -exec grep -H "" {} \;
.git/refs/heads/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3
.git/refs/remotes/origin/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3
Теперь делаем новый коммит в master local и пушимся.
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 249 bytes | 249.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /Volumes/data/chiv/zablots/gitbook/local/../remote
* [new branch] master -> origin/ololo
$ find .git/refs -type f -exec grep -H "" {} \;
.git/refs/heads/master:be36ec1dfb9fdc267936cfa0d37f4dd84baecbfb
.git/refs/remotes/origin/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3
$ git log --pretty=oneline --abbrev-commit
be36ec1 (HEAD -> master) one more commit
f08ce8a (origin/master) from local2
9efa81f from local1
dbe85a9 init repo
Смотрите! Что-то запушилось в ololo, но в локальном репозитории нет этой ветки.
Проверяем, что в remote:
$ find refs -type f -exec grep -H "" {} \;
refs/heads/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3
refs/remotes/origin/ololo:be36ec1dfb9fdc267936cfa0d37f4dd84baecbfb
Ветка появилась, но у неё весьма странное название. То есть конфигурация «push» указывает имя ветки, в точности то, что будет в удалённом репозитории.
Исправляемся. Удалим из remote эту странную ветку и настроим «push» по другому:
push = refs/heads/master:refs/heads/ololo
Пушимся:
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 249 bytes | 249.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /Volumes/data/chiv/zablots/gitbook/local/../remote
* [new branch] master -> ololo
serdgos-MBP:local chiv$
$ git log --pretty=oneline --abbrev-commit
be36ec1 (HEAD -> master, origin/ololo) one more commit
f08ce8a (origin/master) from local2
9efa81f from local1
dbe85a9 init repo
$ find .git/refs -type f -exec grep -H "" {} \;
.git/refs/heads/master:be36ec1dfb9fdc267936cfa0d37f4dd84baecbfb
.git/refs/remotes/origin/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3
.git/refs/remotes/origin/ololo:be36ec1dfb9fdc267936cfa0d37f4dd84baecbfb
Что произошло: мы запушили в новую ветку ololo на remote, при этом origin/master
не сдвинулся.
Смотим, что эта ветка появилась на remote и с мастером ничего не произошло:
$ find refs -type f -exec grep -H "" {} \;
refs/heads/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3
refs/heads/ololo:be36ec1dfb9fdc267936cfa0d37f4dd84baecbfb
Эээксперимент 3
Удалим ветку с ориджина старым синтаксисом.
Зайдём на local и сделаем оттуда push:
$ git push origin :ololo
To /Volumes/data/chiv/zablots/gitbook/local/../remote
- [deleted] ololo
Посмотрим, что на remote:
$ find refs -type f -exec grep -H "" {} \;
refs/heads/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3
Ветка, которую мы там создали в предыдущем эксперименте удалилась.
Попробуем аналогичным образом грохнуть локальную ветку:
$ git fetch origin +:refs/remotes/origin/master
Ничего не вышло, ветка на месте:
$ find .git/refs -type f -exec grep -H "" {} \;
.git/refs/heads/master:be36ec1dfb9fdc267936cfa0d37f4dd84baecbfb
.git/refs/remotes/origin/master:f08ce8ab2aed7e4dc1917f65fd11b71d8a610fc3
Собственно, конспект
The Refspec
Так мы задаём, как во время фетча автоматически маппить удалённые ветки на локальные.
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/*:refs/remotes/origin/*
Можно задавать несколько правил одновременно:
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/experiment:refs/remotes/origin/experiment
Так можно гибко использовать пространства имён, чтобы ограничивать фетчи:
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/qa/*:refs/remotes/origin/qa/*
Начальный + — опциональный флаг, который говорит, что ссылки нужно обновлять
даже если они не фастфорвард. Тут было бы неплохо провести эээксперимент 1.
Можно настраивать разовный маппинг в момент фетча, как с одной спецификацией, так и с несколькими:
$ git fetch origin master:refs/remotes/origin/mymaster
$ git fetch origin master:refs/remotes/origin/mymaster \
+topic:refs/remotes/origin/topic
Pushing Refspecs
Аналогично можно спецификацию для пуша или использовать разово:
$ git push origin master:refs/heads/qa/master
или
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/*:refs/remotes/origin/*
push = refs/heads/master:refs/heads/qa/master
Тут было бы неплохо провести эээксперимент 2
Deleting References
Если в мапинге пуша скомандовать пуш из «ничего», то целевая ветка удалится:
git push origin :topic
Эквиалентная команда:
git push origin --delete topic