Создать посреднический коммит в истории - PullRequest
1 голос
/ 28 мая 2019

Мне было поручено тиражировать наше централизованное решение VCS в репозиторий git.Мой план состоит в том, чтобы использовать конвейер Jenkins для получения коммитов из CVCS, извлекать последние изменения из git, а затем фиксировать эти изменения в git и push.

Цель состоит в том, чтобы захватить каждый коммит по мере его поступления, для которого яЯ использую веб-крюк из CVCS, который передает соответствующую информацию в конвейер для определения конкретного коммита в истории.Для целей этого вопроса предположим, что вся разработка выполняется в одной бесконечной строке без ветвей.

Меня беспокоит асинхронный характер вызова webhook.Если я зафиксировал 1000, синхронизированных с git, то коммиты 1001 и 1002 будут работать почти одновременно, конвейер Jenkins может запустить 1002 до 1001. Это само по себе не проблема (я намерен включить текстовый файл в репозиторий git).отслеживать последнюю синхронизированную фиксацию CVCS), но было бы хорошо , если бы я мог обрабатывать 1001 более разумным способом, чем отказываться от него.

Есть ли способ создатьпосредник в истории git?Что-то вроде:

git checkout HEAD~1
git checkout -b some_temp_branch
git commit -m "This is commit 1001"
git checkout master
git merge some_temp_branch -Xtheirs         # or something?

, где результирующая история идет от:

1002
 |
1000

до

1002
 |
1001
 |
1000

без изменений в рабочем каталоге?

Ответы [ 2 ]

3 голосов
/ 29 мая 2019

Если вы конвертируете в Git или хотите создать зеркало своего хранилища в Git, эти инструменты уже существуют . Насколько они развиты, зависит от VCS. Например, git-svn очень хорошо развито; Git может действовать как двустороннее зеркало Subversion. Другие доступны онлайн, ищите <vcs name>2git. Например, если вы используете CVS, вы бы искали cvs2git или git cvsimport.

Если инструмент миграции Git еще не существует для вашей VCS, вы можете создать его, превратив свои коммиты в формат, подходящий для git fast-import. Вместо того, чтобы привлекать Jenkins, вы бы использовали обычный клиент VCS для получения последних коммитов; тогда не будет проблем с заказом.


Если вы хотите перейти на Git, я бы порекомендовал инвертировать ваш процесс. Какой подход лучше всего, зависит от вашей ситуации, но обычно лучше использовать Git в качестве хранилища лидеров, а вашу старую VCS - в качестве последователя. Git очень гибкий и мощный. Он может адаптироваться к тому, как вы использовали вашу старую VCS, но ваша старая VCS не может адаптироваться к Git. Создание Git-подписчика ограничивает вас тем, что вы используете контроль версий так же, как и сейчас; какой смысл конвертировать?

Если Git является лидером, Git может действовать в централизованном режиме, как вы привыкли. Обязательно выполняйте коммит только на master и всегда помещайте свои локальные коммиты на кончик мастера, используя git pull --rebase перед нажатием. Тем временем вы можете изучить новые возможности Git; например, функциональные ветви . Если необходимо сохранить старую VCS, создайте зеркало только для чтения, отразив коммиты на ветку master старой VCS.

0 голосов
/ 29 мая 2019

Стоит отметить, что независимо от того, как вы делаете это, вы получаете не вставленный коммит.

Если вы сделаете ребазинг - как бы вы его ни делали - вместо этого вы получите новую ветку , заканчивающуюся новым коммитом. Новая ветвь может повторно использовать имя старой ветки (что приводит к очевидному вопросу: Что именно мы подразумеваем под "ветвью"? ), но ваша новая цепочка фиксации будет иметь новые и другие хэш-идентификаторы из вашей исходной цепочки коммитов.

То есть, если у вас было:

... <-c1000a <-c1001a   <-- master

потому что ваша система думала, что c1001 должен прийти сразу после c1000, и теперь стало понятно, что нет, между ними должен быть коммит, вы можете сделать новый c1001b:

... <-c1000a <-c1001a   <-- master
            \
             c1001b

но теперь вы должны скопировать то, что было c1001a в c1002b:

... <-c1000a <-c1001a   <-- master
            \
             c1001b <- c1002b

Теперь вы можете иметь имя master, указывающее на c1002b, "забывая" c1001a полностью:

... <-c1000a <-c1001a
            \
             c1001b <- c1002b   <-- master

Забытый коммит продолжает существовать (и быть действительным) до тех пор, пока Git где-то запоминает свой хэш-идентификатор (обычно в записи reflog , в течение 30+ дней, за исключением серверов репозитория --bare). где нет льготного периода). Если какой-то другой Git захватил c1001a, то другой Git сохранит его и может объединить его с c1002b - или каким бы ни был последний совет master - позже, так как , если они оба были названы master, вы, вероятно, захотите объединить c1001a. (Вы действительно не знаете, но Git не знает этого.)

Если вы сливаетесь, вы просто получаете коммит слияния в конце. Вы добавляете коммит в новую временную ветку:

             c1001a   <-- master
            /
... <-c1000a
            \
             c1001b   <-- temporary

, а затем git checkout master; git merge -s ours temporary, чтобы сохранить исходное дерево из c1001a:

             c1001a
            /      \
... <-c1000a        c1002a   <-- master
            \      /
             c1001b   <-- temporary

Стирание временного имени дает вам окончательный результат:

             c1001a
            /      \
... <-c1000a        c1002a   <-- master
            \      /
             c1001b

, который не даст другим репозиториям Git никакой изжоги, поскольку вы не сознательно выбросили плохой коммит в пользу новой и улучшенной версии (которую другой Git может затем вернуть) , Вместо этого вы просто добавили коммитов, которые все Гиты понимают как другие Гиты в любое время.

Недостатком метода слияния является то, что, возможно, это неправильная история.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...