Как перенести git-снимки из частного git-репозитория в публичный git-репозиторий? - PullRequest
1 голос
/ 09 апреля 2019

У меня есть два репозитория git:

  1. Приватный для разработчиков и их ежедневных коммитов
  2. И публичный для публичных релизов.

Всякий раз, когда я хочу выпустить код, я хочу отправить снимок репозитория разработчика в общедоступное репо. Поскольку репозиторий разработчика может содержать некоторые сообщения о фиксации, которые не подходят для общего пользования, я хочу отправить в публичное репо новое сообщение о фиксации.

Моя идея была (при условии, что я нахожусь в основной ветке репозитория dev):

// create remote 
git remote add p_repo git://some_repo
// create orphaned branch to get rid of commit history
git checkout --orphan pub_sync
// commit 
git commit -m "release info"
// push local master to remote master
git push p_repo pub_sync:master

Это работает впервые, когда публичное репо пусто. Но для второго публичного толчка я получаю ошибку перемотки вперед. В то же время не было никакого другого обязательства по публичному репо!

Полагаю, проблема в том, что git не знает, что потерянная ветвь связана с публичным мастером.

Но как я могу решить это?

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Проблема в том, что вы пытаетесь отправить новый коммит на удаленный мастер, из которого недоступен коммит, находящийся в данный момент на удаленном мастере.В первый раз, когда вы это сделали, предположительно, на пульте не было коммитов.Итак, вы начали с

O -- x ... x -- A <--(master)

в вашем локальном репо.Вы создаете потерянную ветвь и нажимаете, так что теперь у вас есть

O -- x ... x -- A <--(master)

R1 <--(pub_sync)(p-repo/master)

Теперь вы не сказали явно, как вы делали это во второй раз, но похоже, что вы либо удалили локальную ветку pub_sync,или сделал что-то эквивалентное.(Потому что в противном случае, если выполнить те же действия, что и выше, создание ветки не удастся.) Поэтому после того, как вы выполнили какую-то разработку и еще один новый checkout --orphan, у вас будет

O -- x ... x -- A -- x .. x -- B <--(master)

R1 <--(p-repo/master)

R2 <--(pub_sync)

Возможно, это то, что вы имели в виду в git«не зная», что новая сиротская ветвь связана с удаленным master, в этом случае вы правы.Теперь вы могли бы принудительное нажатие pub_sync, но я не рекомендую этого по двум причинам: во-первых, принудительное нажатие не должно быть обычной частью вашего рабочего процесса.Во-вторых, поскольку вы храните релизы в репозитории, я предполагаю, что вы хотите сохранить там историю релизов.

Что вам действительно нужно, так это создать R2 как дочерний элемент R1.

В другом ответе кто-то предлагает слияние сквоша;проблема в том, что вам придется вручную отслеживать базу слияния.Есть шаблон, по которому вы можете следовать, когда вы сначала делаете истинные слияния с промежуточной ветвью, а затем повторно применяете только этот патч к конечной ветке выпуска;но это, вероятно, излишне для вашего случая использования.В качестве альтернативы вы можете создать ссылку для представления базы слияния, и не забывайте перемещать ее после каждого слияния в сквош.Кроме того, вопреки инструкциям из другого ответа, если вы не хотите рисковать, случайно выставив dev-коммиты в prod-репо, вам нужно будет выполнить слияние сквоша на стороне dev и выдвинуть только результат.

Или вы можете использовать commit-tree;это тоже немного хлопотно, но, возможно, можно было написать сценарий или создать псевдоним.Вы бы не удалили / переориентировали синхронизирующую ветку;поэтому, начиная с

O -- x ... x -- A -- x .. x -- B <--(master)

R1 <--(pub_sync)(p-repo/master)

, вы бы

git checkout pub_sync
git merge $(git commit-tree -p HEAD -m "commit message" master)
git push p-repo pub_sync:master
0 голосов
/ 09 апреля 2019

TL; DR

Использование git merge --squash --no-commit

Детали

Для первого коммита ваша процедура звучит как находка.

Для последующих коммитов я бы использовал

git merge --squash --no-commit

Чтобы это работало, вам нужна песочница как с вашим репо-разработчиком, так и с вашим публичным репо, как вы и сделали, хотя я ожидаю, что было бы проще, если бы песочница была клоном публичного репо.

Вот процедура, которая должна работать:

git clone public_repo
cd public_repo
git remote add dev dev_repo_url
git fetch dev
git merge --squash --no-commit dev/master
git commit -m'updated to version X'
git push

Результаты, которые вы получите от git merge --squash --no-commit, не будут иметь никаких подключений к вашему репозиторию dev, а только передают состояние файлов в вашу песочницу, которую вы затем можете зафиксировать в качестве следующего шага.

Возможно, вам понадобится добавить -Xtheirs, если слияние приведет к конфликтам, так как я предполагаю, что вам нужно именно состояние dev/master, а не некоторое слияние ветвей public и dev.

Почему

Смысл этого подхода в том, что новый коммит имеет предыдущую общедоступную версию в качестве своего родителя, что вам и нужно в вашем публичном репо. Вы получили ошибку из-за того, что новая версия не является дочерней по отношению к предыдущей, а является новым рутом, что обычно не рекомендуется.

...