git: Застосовуйте зміни, внесені при здійсненні в одному репо, до іншого репо


115

У мене є repo1і repo2на локальній машині. Вони дуже схожі, але остання - це якась інша галузь ( repo1вже не підтримується).

/path/to/repo1 $ git log HEAD~5..HEAD~4
<some_sha> Add: Introduce feature X

Як застосувати зміни , зроблені фіксації <some_sha>в repo1до repo2?

Чи потрібно мені підготувати якийсь пластир, чи можна зробити якийсь cherry-pickміж репост?

Як щодо того, як робити те ж саме, але для діапазону комітетів?


2
Ви не можете просто перейти від repo1 до repo2?
zwol

для трохи більш конкретного випадку, коли ви хочете застосувати зміни до файлу або файлів, переміщених в одне із сховищ, дивіться тут: stackoverflow.com/questions/3491270/…
Braham Snyder

Відповіді:


31

Як хак, ви можете спробувати змінити рецепт порівняння комісій у двох різних сховищах на сторінці GitTips , тобто:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects \
git cherry-pick $(git --git-dir=../repo/.git rev-parse --verify <commit>)

де ../repoшлях до іншого сховища.

У сучасному Git ви можете використовувати декілька версій та діапазонів ревізій із вишневим вибором .

$(git --git-dir=../repo/.git rev-parse --verify <commit>) Тут , щоб перевести <commit>(наприклад HEAD, чи v0.2, або master~2, які є значеннями в другому сховище скопійованого з) в SHA-1 ідентифікатор фіксації. Якщо ви знаєте SHA-1 зміни, яку хочете вибрати, це не обов'язково.

Зауважте, що Git може пропустити копіювання об'єктів із вихідного сховища, оскільки він не знає, що альтернативний сховище об'єктів є лише тимчасовим для однієї операції. Можливо, вам доведеться скопіювати об’єкти з другого сховища за допомогою:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects git repack -a -d -f

Це ставить ці об'єкти, запозичені з другого сховища, в оригінальному сховищі репозиторію

Не перевірений.


Не настільки шалений рішення - це слідувати відповіді на трикотаж :

  • Перейдіть до другого сховища, з якого ви хочете скопіювати документи, та генеруйте виправлення із комітетів, які ви хочете git format-patch
  • За бажанням скопіюйте виправлення (0001- * тощо) у ваше сховище
  • Використовуйте git am --3wayдля нанесення патчів

1
Добре працює. Якщо у вас проблеми з фіксацією, виконайте скидання HEIT; git add. '.
гумік

5
це приголомшливо - як би ви зробили цілий спектр комітетів? просто sha1 ... sha2?
hvgotcodes

Я також отримую, fatal: unable to read tree ...але після git reset HEAD^того, як все працює добре
jmarceli

@hvgotcodes він працював для мене просто пропускання діапазону, <commit>але rev-parse --verifyкоманда не подобається, як вона приймає тільки одну фіксацію значення. Але, cherry-pickприймаючи значення однократного та діапазонного фіксування, я запитую: навіщо це rev-parseпотрібно?
Чуїм

1
@Chuim: git rev-parseнеобхідно , якщо ви хочете звернутися до фіксації його реф на основі імені в іншому сховищі, наприклад master, HEAD^^або що - то в цьому роді; rev-розбір перетворює його в універсальний ідентифікатор SHA-1.
Якуб Нарубський

207

Ви, ймовірно, хочете використовувати, git format-patchа потім git amзастосувати цей патч до вашого сховища.

/path/to/1 $ git format-patch sha1^..sha1
/path/to/1 $ cd /path/to/2
/path/to/2 $ git am -3 /path/to/1/0001-…-….patch

Або в одному рядку:

/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3

9
Це рішення виявилося простішим та безпечнішим, ніж прийнята відповідь на пряме збирання вишень GIT_ALTERNATE_OBJECT_DIRECTORIES(що може зіпсувати моє сховище).
Чуїм

2
Якщо виникають конфлікти, це не спрацює, оскільки не вдається знайти комітети на іншій гілці.
Роджер Фар

2
Додавання --ignore-whitespaceдо git amкоманди може вирішити будь-які конфлікти та уникнути необхідності виконувати 3-х
напрямне

97

Це можна зробити, cherry-pickякщо ви додасте друге репо як віддалене до першого (а потім fetch).


11
Це насправді правильний спосіб зробити це.
Вільберт

5
Це відчуває себе правильним шляхом і для мене. І я просто використовував це, і він добре працював на мене.
Рікі Нельсон

11
Я б швидше сказав: роби git fetch [remote-name]у другій репо і тоді git cherry-pick [sha1].

5
Такий підхід спрацював для мене чудово, дякую. Оскільки друге репо було також локальним, просто довелося використовувати URI-файл при додаванні його як пульт.
palimpsestor

2
У моєму випадку у мене є два клони гігантського віддаленого сховища git (щоб дозволити паралельну роботу), тобто вся його історія вже завантажена та збережена у моєму HD. Якби мені також довелося додати кожну як віддалений від іншого, це створило б ще дві додаткові копії тієї самої історії і потенційно вимагало б синхронізації між ними, перш ніж я зможу cherry-pick. Тож, хоча це може здатися «правильним», це не завжди є найбільш практичним.
Чуїм

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.