Создание Git-патчей для двух файлов в нескольких переименованиях.
Я хочу переместить два файла из одного хранилища в другое. Файлы были изначально добавлены как:
/src/init/Price.cs
/tests/init/PriceTests.cs
Два файла были позже переименованы в:
/src/init/PriceValue.cs
/tests/init/PriceValueTests.cs
И затем перешел к:
/src/moved/PriceValue.cs
/tests/moved/PriceValueTests.cs
Я пытался использовать это описание для создания набора исправлений для этих файлов, но я не уверен, как передать шесть различных путей, по которым существовали файлы.
Мне удалось найти все идентификаторы фиксации, влияющие на PriceValue.cs
(через переименования и перемещения), но передача этих идентификаторов в Git завершается неудачно со следующим сообщением об ошибке:
$ git format-patch -o /tmp/pricevaluepatches $(git log --all dfeeb 6966b 9f882 …)
-bash: /usr/local/bin/git: Argument list too long
Итак, как мне создать набор патчей для этого, который содержит только изменения в упомянутых файлах, но содержит его по одному переименованию и одному перемещению каждого файла?
3 ответа
Вы можете получить патчи для нескольких конкретных файлов, но не раньше, чем совершитьsha1
с помощью
git format-patch sha1 -- file1 file2 ...
Любой из файлов может быть старым файлом (до переименования) или существующим файлом.
Если вы хотите, чтобы все коммиты до коммитаsha1
ты можешь использовать
git format-patch --root sha1 -- file1 file2 ...
Так что в вашем случае все фиксирует до сих пор (HEAD
) из ваших шести файлов:
git format-patch --root HEAD -- /src/init/Price.cs /src/init/PriceValue.cs /src/moved/PriceValue.cs /src/init/PriceTests.cs /src/init/PriceValueTests.cs /src/moved/PriceValueTests.cs
Чтобы достичь цели из вопроса с помощью слияния (вместо того, чтобы отдельный патч перемещался с помощью format-patch в соответствии с заданным вопросом), можно удалить все другие файлы в новом коммите, а затем объединить эти коммиты между репозиториями в целевой репозиторий (адаптированный из /questions/6247601/kak-obedinit-dva-repozitoriya-git/6247662#6247662):
cd path/to/project-a
git checkout -b for-b master # or whichever branch you want to merge from
git rm -r .
git checkout HEAD -- src/moved/PriceValue.cs tests/moved/PriceValueTests.cs
git commit
cd path/to/project-b
git remote add project-a path/to/project-a
git fetch project-a
git merge --allow-unrelated-histories project-a/for-b
git remote remove project-a
cd path/to/project-a
git branch -D for-b
Преимущество этого в том, что вся история существует, идентификаторы коммитов остаются неизменными, и нет необходимости ни манипулировать отдельными коммитами, ни искать их. Это может иметь тот недостаток, что линеаризованный вид (например, git log
), в отличие от представления графика (как gitk
), вероятно, становится все более запутанным, поскольку число несвязанных коммитов становится больше.
Можно дополнительно отфильтровать хранилище project-a
перед слиянием, чтобы скрыть несвязанные файлы или коммиты. Однако недостатком этого является то, что: если вы делаете это по слиянию репозитория более одного раза, возможно, и в другом направлении, это делает историю менее чистой, так как общая история встречается только несколько раз (один раз для каждого слияния). Это также сделало бы это решение более сложным, чем изначально пробованное. Это также имело бы недостаток, заключающийся в том, что идентификаторы коммитов не остаются прежними, и, следовательно, было бы не так просто найти, какие коммиты были одинаковыми в репозиториях.
Хм..... Предполагая, что я хочу сохранить файлы патчей такими, какие они есть, я бы применил файл патча к ветке, чтобы потом можно было выбрать его в правой ветке.
Итак, предположим, что у меня в главной ветке есть файл с именем /tests/moved/PriceValueTests.cs, и я хочу применить к нему патч с именем /tests/init/PriceTests.cs. Предполагая, что я не хочу взламывать файл патча, я бы сделал следующее:
- создать временную ветку от моего хозяина
- оформить временную ветку
- переименуйте файл по тому же пути, что и у файла патча (и, конечно, зафиксируйте)
- применить файл патча к временной ветке (должен работать теперь, когда путь к файлу имеет соответствующий файл)
- совершить на временной ветке
- мастер проверки
- Вишневое дерево последней ревизии из временной ветки
Это сделано для того, чтобы git мог отслеживать изменение имени и успешно применять его. Я делал это несколько раз, и алгоритм переименования файлов в git имеет тенденцию делать это правильно.