Изменить: Вы на правильном пути в своем собственном ответе: выбор вишни почти наверняка является способом go для вашего фактического случая. Уловка состоит в том, чтобы поместить их исходное дерево в качестве «сиротской ветки» (независимая фиксация), а затем вставить их патч в качестве второй фиксации в этой ветке, а затем вернуть go в свою собственную ветку и использовать git cherry-pick
. Выбор вишни внутренне реализован как полное трехстороннее слияние, при этом база слияния является родительским элементом фиксации, выбранной вишневой, а фиксация --theirs
является фиксацией, которую вы называете.
Инструкции
В вашем исходном репозитории (или добавленном рабочем дереве для этого репозитория, если вы не хотите связываться с вашим основным рабочим деревом), выполните:
git checkout --orphan xxx # use any name you like here
git read-tree -m -u 4b825dc642cb6eb9a060e54bf8d69288fbee4904
The ha sh ID здесь - это пустое дерево . Логически использование --empty
должно работать здесь, но не работает. Или вместо дерева чтения используйте:
git rm -r .
, который делает то же самое, и в качестве бонуса его легче вводить, но он почему-то выглядит страшнее. ?
Ваше рабочее дерево теперь должно быть пустым, а git status
скажет:
On branch xxx
No commits yet
nothing to commit (create/copy files and use "git add" to track)
Если ваше рабочее дерево не пусто, оно ранее содержало неотслеживаемые файлы и все еще содержит. Вы должны переместить или удалить их (или, опять же, вы можете сделать все это в добавленном рабочем дереве).
Теперь сделайте то, что вы предложили в своем собственном ответе:
# copy my Baseline folder changes in
git add .
git commit -m "baseline"
( примечание: не используйте git commit -a
; он не делает того, что вы хотите).
Я понял, что «набор изменений» означает «различие, которое вы примените», а не «новый набор файлов. ". Набор изменений - неправильное слово для описания нового снимка, но если это новый снимок, пора снова очистить дерево работы:
git rm -r .
, чтобы использовать версию, которую проще ввести. Затем снова почти прямо из вашего собственного ответа:
# copy my ChangeSet folder changes in
git add .
git commit -m "code"
Теперь вы можете git checkout master
и git cherry-pick xxx
. Замените любое имя ветки, которое вы используете для хранения двух коммитов.
[Исходный ответ ниже.]
Я бы хотел выполнить 3-стороннее слияние изменений с ChangeSet
на Repo1
. Я рассмотрел возможность создания временного репозитория, содержащего два коммита,
У вас хотя бы один недостаток. Слияние имеет три входов, а не два:
первый для базовой линии и второй для набора изменений, а затем слияние с --allow-unrelated-stories:
Вы на правильном пути, используя первый вариант в качестве базового.
Два других, которые вам понадобятся:
- один с базовым уровнем. -plus-changes: это их код или
--theirs
сторона слияния и - с вашим кодом: это сторона
--ours
слияния. Это коммит, который вы получите как HEAD
в результате выполнения git checkout
.
Оба этих коммита исторически должны происходить от базового уровня. Таким образом, Git может сравнить снимок базы слияния - в данном случае базовый уровень - с каждым из двух снимков кончика ветки : вашего кода и их-code-as- изменен-их-набором изменений.
Следовательно:
# create initial commit in initial repository:
git init # create new empty repository
... # copy baseline into place
git add .
git commit
# add their changeset as a new commit on a branch:
git checkout -b theirs
... apply the changeset, perhaps with "git apply" ...
git add -u # or git add . again, or similar
git commit
# add your version of the code as a new commit on master:
git checkout master
... copy your code into place ...
git add . # or similar
git commit
Теперь вы можете запустить git merge theirs
. Три входных параметра - это базовая фиксация слияния, текущая фиксация - вершина master
, также известная как HEAD
- и фиксация, которую вы называете: окончательная фиксация ветки theirs
.
* Команда 1090 * самостоятельно находит базовый коммит слияния. В данном случае это базовые файлы в начальной фиксации. Команда git merge
теперь создает два набора изменений:
- baseline vs
HEAD
: это то, что вы изменили; - baseline vs
theirs
: this это то, что они изменили.
Обратите внимание, что это второе сравнение дает набор изменений, который вы использовали для создания theirs
коммита и его снимка. Это может показаться напрасной тратой усилий - почему бы просто не передать Git набор изменений напрямую? - но ведь именно так построен Git: Git действительно нужен этот снимок, поэтому вы должны его создать.
Что делать, если у вас уже есть репозиторий, и вы хотите выполнять работу прямо там?
В этом случае вы в некоторой степени связаны (в смысле «проблематично c ситуация »). Git находит базу слияния самостоятельно. Вы не можете просто сказать Git: выполнить слияние, делая вид, что фиксация C является базой слияния для некоторой произвольной фиксации C. 1
Один вариант - переписать весь ваш репозиторий в структуру, которая позволяет это. Как правило, это плохая идея, если вы действительно не хотите переключиться на новую историю, отбросив также все клоны.
Другой вариант - создать второй репозиторий или независимый подграф в вашем репозитории. Это отлично работает: используйте git checkout --orphan
и git read-tree --empty -u
, чтобы получить чистый лист для новых отключенных ветвей (конечно, не называйте основной master
). Затем вы можете ie новую фиксацию слияния в исходную историю в вашем основном графике. Это немного сложно.
Третий - использовать git replace
для вставки родительского графа, чтобы в вашем репозитории появилась новая root фиксация. Это тоже немного сложно. Он эквивалентен второму методу, за исключением того, что он оставляет меньше следов того, как вы это сделали: независимо от того, оставляете ли вы заменяющую фиксацию на месте или нет, она не копируется при операциях клонирования, поэтому другие пытаются выяснить, как вы сделали то, что вы сделали , вероятно, будет озадачен.
Последний вариант - тот, который вы описали сами:
... Я мог бы использовать git-merge-file
для слияния любых небинарных файлов, которые могут существовать во всех трех местах, а затем обработка всех двоичных конфликтов, добавление, удаление файлов и т. д. c. я сам ...
Этот метод также отлично работает, и вы можете автоматизировать многие из них с помощью сценария; это все еще немного болезненнее, чем сделать это Git.
1 На самом деле вы можете сделать это, используя git merge-recursive
. Однако эта команда не предназначена для запуска пользователем. Нет документации, объясняющей , как его запускать, и аргументы сложны: некоторые из них предоставляются как переменные среды! Не делай этого так.