Сделать потерянную ветку из существующего репозитория?
У меня есть git-репозиторий, на котором я провел некоторое тестирование, и я хотел бы включить его в основной репозиторий.
Я хотел бы добавить это как потерянную ветку, потому что я хочу сохранить ее, но я не хочу раздувать основную ветку с моим тестовым проектом.
Как я могу импортировать git-репозиторий как осиротевший брах? Я хотел бы сохранить свои коммиты.
Отредактируйте, чтобы показать, что это не дубликат: на самом деле мне было все равно, что он будет осиротевшим или что-то в этом роде, я просто хотел объединить два хранилища. Данный ответ правильный и решает мою проблему.
1 ответ
Я думаю, что вы смотрите на это неправильно. На самом деле, существование этого вопроса подразумевает нечто неправдивое. Я думаю, что вы хотите, правильнее назвать "непересекающиеся подграфы".
Чтобы попасть туда, перенеси меня через это следующее упражнение. Если вы просто хотите получить ответ, прокрутите вниз.:-)
Упражнение: какая ветвь осиротела?
Представьте, что у вас есть хранилище, и в этом хранилище есть две ветви с именем X
а также Y
(нет master
, просто X
а также Y
). Ветка X
указывает на фиксацию a123456
и филиал Y
указывает на фиксацию b987654
, Эти коммиты, как обычно, указывают на их родителей, но если мы рисуем весь граф коммитов (репозиторий маленький, так что это хорошо вписывается в этот SO-ответ), мы получим:
o--o--o--o <-- X
o--o--o---o <-- Y
\ /
o--o
Есть два разных корневых коммита. Ветка X
указывает на a123456
который является вершиной цепочки с четырьмя коммитами с корнем в a000000
, Ветка Y
указывает на b987654
который является коммитом кончика слияния структуры с шестью коммитами, основанной на b000000
,
Какая ветвь (и), если есть, является сиротской ветвью?
(Это хорошее место, чтобы остановиться и подумать над этим вопросом.)
Если вы выбрали X
почему вы выбрали именно этот? Если вы выбрали Y
почему вы выбрали именно этот? Если бы вы выбрали оба, я думаю, вы могли бы оправдать этот выбор; но если бы вы не ответили ни на что, я бы назвал это правильным и заметил, что вы теперь согласились с Git.
(Если вы выбрали оба X
а также Y
какова ваша причина называть эти "сиротские ветви"? Я думаю, что вы могли бы поспорить за это как правильный ответ и обосновать это, сказав, что ни один из них не связан с master
, Если мы тогда добавили ветку с именем master
и сделал это указать на любой из четырех коммитов на X
, тогда вы бы сказали, что филиал Y
осиротевший и X
не является. Если вы сделали master
указать на любой из шести коммитов на Y
, вы бы тогда сказали, что X
это сирота и Y
больше не осиротел. Вероятно, есть и другие способы решения, в зависимости от того, насколько вы хотите изменить то, как вы определяете "сирота". Но это не то, что означает Git, и на самом деле, есть лучшая терминология, которая не будет противоречить Git и будет служить вам лучше в долгосрочной перспективе.)
Несвязные подграфы
В нашем примере репозитория упражнений выше, ни X
ни Y
была сиротская ветвь, потому что у обоих есть коммиты на них. В теории графов - репозитории Git построены вокруг теории графов - двух ветвей имен X
а также Y
указывают на непересекающиеся подграфы общего графа.
Примечание: что Git подразумевает под ветвью сироты
В Git, сиротском филиале, созданном с git checkout --orphan newbranch
, является отраслью в особом состоянии, "еще не родиться". Это состояние длится до тех пор, пока в ветви не будут зафиксированы коммиты, после чего ветка больше не будет "сиротской ветвью". Теперь это просто обычная ветка, как и любая другая.
Git фактически реализует состояние ветвления-сироты таким образом, что абстракция протекает довольно сильно. В частности, он записывает имя новой ветви в HEAD
, но больше нигде. поскольку HEAD
содержит имя текущей ветви, если вы извлекаете любую другую ветку, это перезаписывает HEAD
файл, и сама сиротская ветвь полностью исчезает. Другими словами, только одна отдельная ветвь может быть когда-либо в "сиротском" состоянии, и она попадает туда, сохраняя свое имя в HEAD
и только в HEAD
, поскольку HEAD
хранит название текущей ветви, только текущая ветвь может быть сиротой.
Наконец, ответ на то, что я думаю, ваш вопрос на самом деле
Имея два несвязанных репозитория R1 и R2, вы хотите создать объединение репозитория (возможно, новое хранилище R3, возможно, просто изменив одно из двух исходных репозиториев), чей граф фиксации является непересекающимся графом, возникающим из объединения двух графов фиксации в R1 и R2
Давайте сделаем это как новый третий репозиторий. (Еще проще просто перевести R1 в R2 или наоборот, пропустив некоторые из этих шагов, поэтому давайте начнем с полного упражнения, и вы можете уменьшить его, если хотите.)
Чтобы построить новый репозиторий R3, сначала создайте пустой репозиторий:
$ mkdir r3 && cd r3 && git init
Теперь извлеките все из R1 в R3. Вы можете сделать это, добавив R1 в качестве именованного удаленного (это почти наверняка так, если вы добавляете R2 в R1, хотя тогда мы сейчас в R1 добавляем R2, а не в R3 добавляем R1). Вы могли бы просто бежать git fetch
и дать ему URL-адрес и использовать информацию о ветвях, что он падает в FETCH_HEAD
, но давайте пойдем с добавлением обоих как пультов. <url>
тут могут быть пути (../../otherrepo.git
или же /path/to/otherrepo.git
), или же ssh://...
или же git://...
или же https://...
, по-прежнему.
Затем извлеките все из R2 в R3. Мы используем точно такие же шаги, только другое удаленное имя и URL:
$ git remote add r1 <url for r1>
$ git remote add r2 <url for r2>
$ git fetch r1; git fetch r2
К этому моменту вы, по сути, готовы: у вас есть объединение в качестве графа коммитов в вашем новом хранилище. Осталось только сделать имена локальных веток, указывающие на те же коммиты, что и некоторые или все ветки удаленного отслеживания.
Так как мы назвали хранилище R1 r1
все его филиалы находятся в refs/remotes/r1/branch-name
, Аналогично, так как мы назвали R2 r2
все его филиалы находятся в refs/remotes/r2/branch-name
, Вы можете ссылаться на них по их сокращенным версиям, r1/whatever
а также r2/whatever
, Скажем r1
имеет филиалы master
а также A
а также r2
имеет филиалы master
а также B
,
Потому что есть только один A
, ты можешь сделать:
$ git checkout A
и теперь у вас есть ветка с именем A
указывая на тот же коммит r1/A
, Кроме того, ваш местный A
настроен на отслеживание r1/A
: то есть его вверх по течению r1/A
,
То же самое относится и к B
,
Вы можете создать новый master
в r3
но он может указывать только на тот же коммит, что и один из двух других репозиториев, и вы не можете использовать этот ярлык. Допустим, вы хотите r3
"s master
соответствовать r2/master
:
$ git checkout -b master r2/master
создаст его и настроит для отслеживания r2/master
,
Если вы не хотите этого вверх по течению --track
настройки, создавайте ветки используя --no-track
,
Вот и все, что нужно сделать: создать эти два непересекающихся подграфа действительно так просто. Вам просто нужно знать, что это то, что вы делаете, и что суетиться с --orphan
требуется только в том случае, если вы хотите органически вырастить новый непересекающийся подграф, а не извлекать его из какого-либо существующего хранилища.