Как применить изменения Git Commit к разным файлам
Git — это мощная система контроля версий, которая позволяет создавать несколько разветвленных версий вашего проекта с автоматическим слиянием. Это здорово, но иногда это ломается, когда файлы переименовываются или находятся не в том месте. К счастью, вы можете вручную применять исправления к различным файлам.
Проблема
При использовании веток Git часто необходимо применять изменения из одной ветки в другую. Обычный вариант использования этого — версионные ветки — если у вас есть старая версия LTS, вы можете захотеть применить случайное исправление к старой версии. Или, возможно, вы предоставляете две сборки программного обеспечения, предназначенные для разных наборов инструментов или сред, и вам необходимо синхронизировать их.
Если ваши ветки имеют одинаковый макет, вы можете использовать git cherry-pick
, который может копировать отдельные коммиты из одной ветки в другую. Например, перетащите фиксацию из ветки функций в master
до того, как все это будет объединено:
Однако программное обеспечение не всегда бывает чистым, и в процессе рефакторинга вы можете столкнуться со случаями, когда файлы были перемещены или переименованы. Git работает с путями к каталогам, поэтому это полностью нарушает git cherry-pick
, поскольку Git не может применять изменения к несуществующим файлам.
Однако в Git есть инструменты для исправления этого, поэтому, когда обычное слияние не работает, вы можете вручную исправить файлы с обновлениями, используя git patch
.
Использование различий и исправлений Git
Чтобы продемонстрировать это, мы создадим пустой репозиторий с одним файлом: Old.java
. С этим файлом создается новая ветвь старая-версия
с некоторыми изменениями. Этот файл был переименован с некоторыми более поздними изменениями в ветке master
на New.java
, что нарушило совместимость между ветвями.
А вот как выглядит история веток, показанная в графическом интерфейсе Git-программы Fork:
В этом примере нам нужно переместить фиксацию «Добавить код» в ветку old-version
. Для этого вам нужно получить идентификатор этой фиксации из справочного журнала:
git reflog
Затем запустите format-patch
с идентификатором и флагом -1
, который создаст файл исправления:
git format-patch 82176b5 -1
Это создаст файл исправления в текущем каталоге. Вы можете переместить его в другую папку в конфигурации .gitignore
, чтобы на нее не повлияло изменение веток.
Затем извлеките ветку старая версия
и примените исправления с помощью утилиты Linux patch
. У Git есть собственные инструменты, git apply
и git am
, которые могут с этим справиться, но, если не считать ручного редактирования файла исправления, у них нет возможности изменить цель. файл в случаях переименования/перемещения.
Вы можете передать имя файла с помощью параметра -p1
и передать файл исправления с помощью -i
.
patch -l -p1 old -i Patches/0001-Add-more-code.patch
Это должно отредактировать файл и добавить изменения, которые вам нужно будет зафиксировать. Одним из недостатков patch
по сравнению с git am
является то, что он не сохраняет информацию о коммите, хотя вы можете найти ее в файле .patch
, если вы хотите сохранить исходное сообщение.
Тем не менее, конфликты слияния все еще могут возникать, если целевая ветка тем временем редактируется, и в этом случае вы застрянете на ручном редактировании, поскольку git merge
не может решить эту проблему за вас. patch
выведет файлы, содержащие различия, которые вам нужно будет исправить вручную.
В качестве альтернативы вы можете переместить целевой файл в целевой каталог, который ожидает Git, что позволит Git выбрать вишенки
и применить изменения. Затем скопируйте файл обратно в исходное место и удалите временный файл.
Патч также может иметь проблемы с окончанием перевода строки (LF) и переводом строки возврата каретки (CRLF), которые могут возникнуть в результате редактирования Windows. Возможно, вам придется переключиться на LF в текстовом редакторе, чтобы патч применялся правильно.