Как переименовать файл в ветке, объединить и иметь два файла с историей в Git?
У меня есть git-репозиторий со следующими ветками:
older:
file (with, say, 10 commits)
newer:
file (10 commits from "older" plus 5 new commits)
Ветвь "новее" была разветвлена от ветви "старше", как некая точка.
Я хотел бы объединить обе ветви в master, иметь обе версии "file" в виде двух разных файлов, и я хочу сохранить историю для обоих:
master:
file-as-seen-in-older (10 commits)
file-as-seen-in-newer (15 commits)
1 ответ
Вот надежный и безопасный способ изменить имя файла, используя git rebase
, Это будет отлично работать в простом случае, когда ваша ветвь newer
и / или older
отклонился от master (или какой-либо другой ветви) и не сливал новые изменения из родительской ветви после этого - полностью удаляя старое имя файла из вашей истории.
(Если такие слияния действительно произошли, то команда все еще безопасна - и конечный результат тот же - но она может не очистить вашу историю так далеко, как вам хотелось бы.)
Выберите, в какую ветку вы хотите изменить имя файла. Оформить заказ на эту ветку. Я предполагаю, что вы выбрали
older
,$ git checkout older
Теперь нам нужно найти базу слияния
older
и его родитель. Это гдеolder
расходится с родителем, создавая новую, независимую историю. Вы можете легко узнать это, просматриваяgit log
или жеgitk
, но мы можем найти его с помощью простой команды. (Я придуmaster
является родителемolder
.)$ git merge-base older master 914b05d90e1de0ff9f89370810888c7f192d65cc $ git tag base 914b05d
В моем хранилище
git merge-base
вывести идентификатор коммита914b05d
, Мы помечаем коммит тегомbase
для удобстваТеперь сделайте интерактивный ребаз на
base
$ git rebase --interactive base
В открывшемся окне редактора убедитесь, что в нем перечислены все коммиты в более старом, начиная с момента, когда он отклонился от своего родителя, до последнего коммита.
- Перейти к первому коммиту.
- Изменить слово
pick
вedit
, Мы скоро отредактируем этот коммит, чтобы переименовать файл. - Теперь посмотрите вниз на другие коммиты. Любые, которые упоминают имя
file
в сообщении коммита нужно будет переписать. + Изменитьpick
вreword
чтобы дать себе возможность перефразировать соответствующие сообщения коммита. - Сохраните файл и выйдите.
Теперь ваш ребаз начнется! git извлечет первый коммит и остановится, ожидая, когда вы внесете изменения в коммит. Здесь мы можем переместить файл и начать перебазирование снова.
$ git mv file file-from-older $ git rebase --continue
git внесет изменения в коммит с вашими изменениями, а затем откроет ваш редактор, чтобы вы могли перефразировать коммит. Изменить любые ссылки на
file
сказатьfile-from-older
вместо. Сохраните файл и выйдите.Любые коммиты, которые вы отметили для
reword
ING также появится в вашем редакторе. Отредактируйте их таким же образом. (Если вы пропустили пометку коммита для переписывания, вы можете сделать это еще раз)Как только ребас закончится, проверьте результат,
git log
, или жеgitk
, Соблюдайте это- Исходное имя файла не существует в вашем рабочем дереве
- или в вашей истории, и что
older
все еще разветвляется от своего родителя в том же месте, а именноbase
,
Если что-то из этого не соответствует действительности, что-то пошло не так (возможно, опечатка), и мы должны отменить коммит. Мы можем сделать это легко с
git reset --hard older@{1}
, который сбрасывает более старое в свое состояние непосредственно перед тем, как произошла перезагрузка. Затем вы можете повторить операцию rebase и выяснить, где она пошла не так.Теперь, когда вы проверили успешность ребазинга, вы можете объединить ваши изменения в
master
или где угодно. Если вы хотите переименоватьfile
в обеих ветках просто повторите процесс дляnewer
филиал также.Наконец, вы можете объединить свои ветви в
master
:$ git checkout master $ git merge older newer
Обнажая любые (не связанные) конфликты, все должно пройти гладко.