Можно ли перемещать / переименовывать файлы в Git и поддерживать их историю?

667

Я хотел бы переименовать / переместить поддерево проекта в Git, перемещая его из

/project/xyz

в

/components/xyz

Если я использую равнину git mv project components, то вся история коммитов xyz projectтеряется. Есть ли способ переместить это так, чтобы история сохранялась?

sgargan
источник
2
Я просто хочу отметить, что я только что протестировал перемещение файлов через файловую систему, и после фиксации (через intellij) я могу затем увидеть всю историю (включая историю, когда она была в другом месте) при просмотре истории (снова в intellij). Я предполагаю, что Intellij не делает для этого ничего особенного, поэтому приятно знать, что, по крайней мере, историю можно отследить.
BT
Правила, которым следует Git при обнаружении переименования каталогов, см. В моем ответе ниже
VonC
Я написал ответ здесь. Надеюсь это работает. stackoverflow.com/questions/10828267/…
Махмут

Ответы:

651

Git обнаруживает переименования, а не сохраняет операцию с фиксацией, поэтому, используете ли вы git mvили mvне имеет значения.

Команда logпринимает --followаргумент, который продолжает историю до операции переименования, т. Е. Ищет похожий контент, используя эвристику:

http://git-scm.com/docs/git-log

Чтобы просмотреть полную историю, используйте следующую команду:

git log --follow ./path/to/file
Троэльс Томсен
источник
63
Я подозреваю, что это соображение производительности. Если вам не нужна полная история, сканирование контента займет больше времени. Самый простой способ - настроить псевдоним git config alias.logf "log --follow"и просто написать git logf ./path/to/file.
Троэльс Томсен
13
@TroelsThomsen, это письмо от Линуса Торвальдса, связанное с этим ответом , указывает на то, что это преднамеренный выбор дизайна Git, так как он, как утверждается, гораздо более эффективен, чем отслеживание переименований и т. Д.
Эмиль Лундберг
127
Этот ответ немного вводит в заблуждение. Git «обнаруживает переименования», но очень поздно в игре; вопрос заключается в том, как вы убедитесь, что Git отслеживает переименования, и кто-то, читающий это, может легко сделать вывод, что Git автоматически обнаружит их и запомнит это. Это не. В Git нет реальной обработки переименований, и вместо этого есть инструменты слияния / регистрации, которые пытаются выяснить, что произошло, и редко делают это правильно. У Линуса есть ошибочный, но яростный аргумент о том, почему git никогда не должен делать это правильно и явно отслеживать переименования. Итак, мы застряли здесь.
Крис Москини
29
Важное замечание: если вы переименуете каталог, например, во время переименования пакета Java, обязательно выполните две фиксации, сначала для команды 'git mv {old} {new}', затем для обновлений всех файлов Java, которые ссылаются на изменил каталог пакета. В противном случае git не сможет отследить отдельные файлы даже с параметром --follow.
nn4l
44
Хотя Линус, вероятно, делает очень мало ошибок, похоже, это одна из них. Простое переименование папки приводит к загрузке огромной дельты на GitHub. Что заставляет меня быть осторожнее с переименованием папок ... но это довольно большая прямая куртка для программиста. Время от времени я ДОЛЖЕН ПЕРЕНОСНОВАТЬ смысл чего-либо или изменить способ классификации вещей. Линус: «Другими словами, я прав. Я всегда прав, но иногда я прав больше, чем в другие времена. И, черт возьми, когда я говорю« файлы не имеют значения », я действительно прав ( тм) «. ... У меня есть сомнения по этому поводу.
Гейб Халсмер
94

Это можно переименовать файл и сохранить историю нетронутым, хотя это приводит к тому , файл будет переименован в течение всей истории репозитория. Это, вероятно, только для навязчивых любителей git-log, и имеет некоторые серьезные последствия, включая следующие:

  • Возможно, вы переписываете общую историю, которая не важна при использовании Git. Если кто-то еще клонировал хранилище, вы сломаете его, сделав это. Им придется повторно клонировать, чтобы избежать головной боли. Это может быть хорошо, если переименование достаточно важно, но вы должны тщательно обдумать это - вы можете в конечном итоге расстроить все сообщество с открытым исходным кодом!
  • Если вы ранее ссылались на файл, используя его старое имя в истории репозитория, вы фактически ломаете более ранние версии. Чтобы исправить это, вам придется сделать больше прыжков с обручем. Это не невозможно, просто утомительно и, возможно, не стоит.

Теперь, так как вы все еще со мной, вы, вероятно, одинокий разработчик, переименовывающий полностью изолированный файл. Давайте переместим файл используя filter-tree!

Предположим, вы собираетесь переместить файл oldв папку dirи дать ему имяnew

Это может быть сделано git mv old dir/new && git add -u dir/new, но это ломает историю.

Вместо:

git filter-branch --tree-filter 'if [ -f old ]; then mkdir dir && mv old dir/new; fi' HEAD

будет повторять каждый коммит в ветви, выполняя команду в тиках для каждой итерации. Много вещей может пойти не так, когда вы сделаете это. Обычно я проверяю, присутствует ли файл (в противном случае он еще не перемещен), а затем выполняю необходимые шаги, чтобы подковать дерево по своему вкусу. Здесь вы можете просматривать файлы для изменения ссылок на файл и так далее. Сбей себя с ног! :)

По завершении файл перемещается, а журнал не изменяется. Вы чувствуете себя пиратом ниндзя.

Также; Разумеется, каталог mkdir необходим только в том случае, если вы перемещаете файл в новую папку. , Если будет избегать создания этой папки ранее в истории , чем существует файл.

Øystein Steimler
источник
57
Как навязчивый любитель git-log, я бы на это не пошел. Файлы не были названы так в те моменты времени, поэтому история отражает несуществующую ситуацию. Кто знает, какие испытания могут сломаться в прошлом! Риск взлома более ранних версий почти во всех случаях не стоит.
Винсент
7
@Vincent Вы абсолютно правы, и я постарался как можно яснее понять, насколько маловероятно, что это решение будет уместным. Я также думаю, что мы говорим о двух значениях слова «история» в этом случае, я ценю оба.
Ойстейн Штаймлер
6
Я считаю, что есть ситуации, когда это может понадобиться. Скажем, я разработал что-то в своей личной ветке, которую я теперь хочу объединить в апстрим. Но я обнаружил, что имя файла не подходит, поэтому я изменяю его для всей своей личной ветки. Таким образом, я могу вести чистую историю и иметь правильное имя с самого начала.
user2291758
3
@ user2291758 это мой вариант использования. Эти более мощные команды git опасны, но это не значит, что у них нет очень убедительных вариантов использования, если вы знаете, что делаете!
philix
1
если возможно, использование --index-filterпереименований будет намного быстрее, поскольку дерево не нужно извлекать и возвращать при каждом коммите. --index-filterдействует непосредственно на каждый индекс коммита.
Томас Гайот-Сионнест
87

Нет.

Краткий ответ - НЕТ . Невозможно переименовать файл в Git и запомнить историю. И это боль.

Ходят слухи, что git log --follow--find-copies-harderэто сработает, но у меня это не сработает, даже если в содержании файла нет нулевых изменений, а ходы были сделаны git mv.

(Изначально я использовал Eclipse для переименования и обновления пакетов в одной операции, что может сбить Git с толку. Но это очень распространенная вещь. --followПохоже, работает, если mvвыполняется только a, а затем a commitи the mvне слишком далеко.)

Линус говорит, что вы должны понимать все содержимое программного проекта в целом, без необходимости отслеживать отдельные файлы. Ну, к сожалению, мой маленький мозг не может этого сделать.

Это действительно раздражает , что так много людей бездумно повторил заявление , что Git автоматически отслеживает движения. Они потратили впустую мое время. Git не делает таких вещей. По замыслу (!) Git вообще не отслеживает ходы.

Мое решение состоит в том, чтобы переименовать файлы обратно в их исходные места. Измените программное обеспечение в соответствии с контролем источника. С Git вам, кажется, просто нужно «сделать» это правильно с первого раза.

К сожалению, это нарушает Eclipse, который, кажется, использует --follow. git log --followиногда не показывает полную историю файлов со сложной историей переименования, хотя и git logделает. (Я не знаю, почему.)

(Есть некоторые слишком умные хаки, которые возвращаются и возобновляют старую работу, но они довольно пугающие. См. GitHub-Gist: emiller / git-mv-with-history .)

Tuntable
источник
2
Я верю, что ты прав. Я просто пытался использовать php-cs-fixer для переформатирования исходного кода для моего проекта Laravel 5, но он настаивает на изменении заглавных букв предложений пространства имен, чтобы они соответствовали строчному значению папки приложения. Но пространства имен (или автозагрузки композиторов) работают только с CamelCase. Мне нужно изменить заглавную букву папки на App, но это приведет к тому, что мои изменения будут потеряны. Это самый тривиальный пример, но он показывает, что эвристика git не способна следовать даже самым простым изменениям имени (--follow и --find-copy-harder должны быть правилом, а не исключением).
Зак Моррис
6
мерзавец -1, подрывная деятельность +1
Космин
Это все еще правда? Это еще одна причина для меня, чтобы сейчас оставаться с tfs, так как хранить историю перемещенного / переименованного файла просто необходимо в большом проекте.
Цезарь
@Cesar Если под «помнить историю» он подразумевает «следовать переименованиям при просмотре журнала» (что является единственной полезной вещью, о которой мы должны заботиться), то это никогда не было правдой! Git не «записывает» переименования, но инструменты могут легко обнаружить их и представить нам переименования и перемещения. Если «это не работает» для кого-то, он / она должен изменить инструменты, которые он / она использует. Есть много замечательных графических интерфейсов Git, которые имеют эту возможность.
Мохаммад Дехган
Короткий ответ: да. Текущая версия Git также поддерживает "git log --follow". и я согласен с @MohammadDehghan
Insung
43
git log --follow [file]

покажет вам историю через переименования.

Эрик Хесселинк
источник
29
Похоже, что для этого требуется совершить только переименование, прежде чем вы начнете изменять файл. Если вы переместите файл (в оболочке), а затем измените его, все ставки отключены.
yoyo
22
@yoyo: это потому, что git не отслеживает переименования, а обнаруживает их. А в git mvосновном делает git rm && git add. Есть варианты, такие как -M90/, --find-renames=90чтобы считать файл переименованным, когда он на 90% идентичен.
vdboor
22

Я делаю:

git mv {old} {new}
git add -u {new}
Джеймс М. Грин
источник
3
Мне кажется, что -u ничего не делает для меня, стоит ли обновлять историю?
Джереми
1
Возможно, вы хотите поведение -Aвместо? Опять же, смотрите здесь: git-scm.com/docs/git-add
Джеймс М. Грин
1
Он добавляет файлы, но не обновляет историю, поэтому «имя файла журнала git» показывает полную историю. Он показывает полную историю, только если вы еще используете опцию --follow.
Джереми
3
Я сделал сложный рефакторинг, который переместил каталог включения (используя mv, а не git mv), а затем изменил множество путей #include в переименованных файлах. Git не может найти достаточно сходства, чтобы отслеживать историю. Но git add -u - это то, что мне было нужно. Состояние git теперь указывает «переименовано», где раньше показывалось «удалено» и «новый файл».
AndyJost
1
Есть много вопросов по SO, которые касаются цели git add -u. Документы Git, как правило, бесполезны и являются последним местом, которое я бы хотел посмотреть. Вот один пост, показывающий git add -uв действии: stackoverflow.com/a/2117202 .
nobar
17

Я хотел бы переименовать / переместить поддерево проекта в Git, перемещая его из

/project/xyz

в

/ Компоненты / хуг

Если я использую равнину git mv project components, то вся история коммитов для xyzпроекта теряется.

Нет (8 лет спустя, Git 2.19, Q3 2018), потому что Git обнаружит переименование каталога , и теперь это лучше задокументировано.

Смотрите коммит b00bf1c , коммит 1634688 , коммит 0661e49 , коммит 4d34dff , коммит 983f464 , коммит c840e1a , коммит 9929430 (27 июня 2018 г.) и коммит d4e8062 , коммит 5dacd4a (25 июня 2018 г.) Элайджей Ньюреном ( newren) .
(Слиты Junio C Hamano - gitster- в фиксации 0ce5a69 , 24 июл 2018)

Это теперь объясняется в Documentation/technical/directory-rename-detection.txt:

Пример:

Когда все из x/a, x/bи x/cпереместились в z/a, z/bи z/c, вероятно, что x/dдобавленные в это время также захотят переместиться z/d, взяв подсказку, что весь каталог x«переехал z».

Но они много других случаев, таких как:

одна сторона истории переименовывает x -> z, а другая переименовывает некоторый файл x/e, вызывая необходимость слияния делать транзитивное переименование.

Чтобы упростить обнаружение переименования каталогов, эти правила применяются Git:

ограничение пары основных правил, когда применяется обнаружение переименования каталогов:

  1. Если данный каталог все еще существует по обе стороны от слияния, мы не считаем его переименованным.
  2. Если подмножество файлов, которые должны быть переименованы, имеют файл или каталог в пути (или будут мешать друг другу), «отключите» переименование каталога для этих конкретных подпутей и сообщите о конфликте пользователю ,
  3. Если другая сторона истории сделала переименование каталога по пути, который ваша сторона истории переименовала, то проигнорируйте это конкретное переименование с другой стороны истории для любых неявных переименований каталога (но предупредите пользователя).

Вы можете увидеть множество тестов t/t6043-merge-rename-directories.sh, которые также указывают, что:

  • a) Если переименовывает разделить каталог на два или более других, каталог с наибольшим количеством переименований, «выигрывает».
  • b) Избегайте обнаружения каталогов-переименований для пути, если этот путь является источником переименования по обе стороны от слияния.
  • c) Применяйте неявные переименования каталогов только к тем каталогам, если переименовывает другую сторону истории.
VonC
источник
15

Задача

  • Использование (вдохновлено от Smar , заимствовано у Exherbo )git am
  • Добавить историю коммитов скопированных / перемещенных файлов
  • Из одного каталога в другой
  • Или из одного хранилища в другое

ограничение

  • Теги и ветки не сохраняются
  • История вырезана по пути переименования файла (переименование директории)

Резюме

  1. Извлечь историю в формате электронной почты, используя
    git log --pretty=email -p --reverse --full-index --binary
  2. Реорганизовать дерево файлов и обновить имена файлов
  3. Добавить новую историю, используя
    cat extracted-history | git am --committer-date-is-author-date

1. Извлечь историю в формате электронной почты

Пример: история Экстракт file3, file4иfile5

my_repo
├── dirA
│   ├── file1
│   └── file2
├── dirB            ^
│   ├── subdir      | To be moved
│   │   ├── file3   | with history
│   │   └── file4   | 
│   └── file5       v
└── dirC
    ├── file6
    └── file7

Установить / очистить пункт назначения

export historydir=/tmp/mail/dir       # Absolute path
rm -rf "$historydir"    # Caution when cleaning the folder

Извлечь историю каждого файла в формате электронной почты

cd my_repo/dirB
find -name .git -prune -o -type d -o -exec bash -c 'mkdir -p "$historydir/${0%/*}" && git log --pretty=email -p --stat --reverse --full-index --binary -- "$0" > "$historydir/$0"' {} ';'

К сожалению вариант --followили --find-copies-harderнельзя сочетать с --reverse. Вот почему история обрезается при переименовании файла (или при переименовании родительского каталога).

Временная история в формате электронной почты:

/tmp/mail/dir
    ├── subdir
    │   ├── file3
    │   └── file4
    └── file5

Дэн Бонэйча предлагает инвертировать циклы команды генерации git log на этом первом шаге: вместо того, чтобы запускать git log один раз для каждого файла, запускайте его ровно один раз со списком файлов в командной строке и генерируйте единый объединенный журнал. Таким образом, коммиты, которые изменяют несколько файлов, остаются в результате одним коммитом, и все новые коммиты сохраняют свой первоначальный относительный порядок. Обратите внимание, что это также требует изменений на втором этапе ниже при перезаписи имен файлов в (теперь объединенном) журнале.


2. Реорганизовать дерево файлов и обновить имена файлов

Предположим, вы хотите переместить эти три файла в этом другом репо (это может быть тот же репо).

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB              # New tree
│   ├── dirB1         # from subdir
│   │   ├── file33    # from file3
│   │   └── file44    # from file4
│   └── dirB2         # new dir
│        └── file5    # from file5
└── dirH
    └── file77

Поэтому реорганизуйте ваши файлы:

cd /tmp/mail/dir
mkdir -p dirB/dirB1
mv subdir/file3 dirB/dirB1/file33
mv subdir/file4 dirB/dirB1/file44
mkdir -p dirB/dirB2
mv file5 dirB/dirB2

Ваша временная история сейчас:

/tmp/mail/dir
    └── dirB
        ├── dirB1
        │   ├── file33
        │   └── file44
        └── dirB2
             └── file5

Измените также имена файлов в истории:

cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'

3. Применить новую историю

Ваш другой репо:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
└── dirH
    └── file77

Применить коммиты из временных файлов истории:

cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am --committer-date-is-author-date

--committer-date-is-author-dateсохраняет оригинальные отметки времени коммита ( комментарий Дана Боначи ).

Ваш другой репо сейчас:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB
│   ├── dirB1
│   │   ├── file33
│   │   └── file44
│   └── dirB2
│        └── file5
└── dirH
    └── file77

Используйте, git statusчтобы увидеть количество коммитов, готовых к отправке :-)


Дополнительный трюк: проверка переименованных / перемещенных файлов в вашем репо

Для просмотра списка файлов, которые были переименованы:

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'

Дополнительные настройки: вы можете выполнить команду, git logиспользуя параметры --find-copies-harderили --reverse. Вы также можете удалить первые два столбца, используя cut -f3-полный шаблон '{. * =>. *}'.

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'
olibre
источник
4
ВНИМАНИЕ: этот метод разбивает коммиты, которые изменяют 2 или более файлов на отдельные фрагментированные коммиты, и, кроме того, скремблирует их порядок путем сортировки по имени файла (поэтому фрагменты одного оригинального коммита не появляются рядом в линейной истории). Таким образом, итоговая история является «правильной» только для каждого файла отдельно. Если вы перемещаете более одного файла, то ни один из новых коммитов в результирующей истории не представляет согласованного снимка перемещенных файлов, которые когда-либо существовали в истории исходного репо.
Дэн Бонача
2
Привет @DanBonachea. Спасибо за ваш интересный отзыв. Я успешно перенес некоторые репозитории, содержащие несколько файлов, используя эту технику (даже с переименованными файлами и файлами, перемещенными по каталогам). Что вы предлагаете изменить в этом ответе. Как вы думаете, мы должны добавить баннер ПРЕДУПРЕЖДЕНИЕ в верхней части этого ответа, объясняющий ограничения этой техники? Приветствия
olibre
2
Я адаптировал эту технику, чтобы избежать проблемы, инвертировав циклы команды генерации git log на шаге 1. Т.е. вместо того, чтобы запускать git log один раз для каждого файла, запустите его ровно один раз со списком файлов в командной строке и сгенерируйте единый объединенный журнал. Таким образом, коммиты, которые изменяют 2 или более файлов, остаются в результате одним коммитом, и все новые коммиты сохраняют свой первоначальный относительный порядок. Обратите внимание, что это также требует изменений в шаге 2 при перезаписи имен файлов в (теперь объединенном) журнале. Я также использовал git am --committer-date-is-author-date, чтобы сохранить исходные метки времени фиксации.
Дэн Боначеа
1
Спасибо за ваши эксперименты и обмен. Я немного обновил ответ для других читателей. Однако я потратил время, чтобы проверить вашу обработку. Пожалуйста, не стесняйтесь редактировать этот ответ, если вы хотите привести примеры командных строк. Приветствия;)
olibre
4

Я следовал этому многоэтапному процессу, чтобы переместить код в родительский каталог и сохранить историю.

Шаг 0: создал ветку 'history' из 'master' для безопасного хранения

Шаг 1: Использовал инструмент git-filter-repo для переписывания истории. Эта команда ниже переместила папку «FolderwithContentOfInterest» на один уровень вверх и изменила соответствующую историю изменений

git filter-repo --path-rename ParentFolder/FolderwithContentOfInterest/:FolderwithContentOfInterest/ --force

Шаг 2: К этому времени репозиторий GitHub потерял свой путь к удаленному репозиторию. Добавлена ​​удаленная ссылка

git remote add origin git@github.com:MyCompany/MyRepo.git

Шаг 3: Извлечь информацию из хранилища

git pull

Шаг 4: Соедините локальную потерянную ветку с исходной веткой

git branch --set-upstream-to=origin/history history

Шаг 5: конфликт слияния адресов для структуры папок, если будет предложено

Шаг 6: Нажмите !!

git push

Примечание. Измененная история и перемещенная папка уже зафиксированы. enter code here

Выполнено. Код перемещается в родительский / нужный каталог, сохраняя историю нетронутой!

Параг Бангад
источник
2

В то время как ядро ​​Git, сантехника Git не отслеживает переименования, история, которую вы отображаете с помощью «фарфора» журнала Git, может обнаружить их, если хотите.

Для данного git logиспользования используйте опцию -M:

git log -p -M

С текущей версией Git.

Это работает и для других команд git diff.

Есть варианты сделать сравнения более или менее строгими. Если вы переименуете файл, не внося при этом значительных изменений в файл, то для журнала Git и его друзей будет легче обнаружить переименование. По этой причине некоторые люди переименовывают файлы в одном коммите и изменяют их в другом.

Использование ЦП требует затрат, когда вы спрашиваете Git, где найти файлы, которые были переименованы, независимо от того, используете ли вы их или нет, и когда, решать только вам.

Если вы хотите, чтобы ваша история всегда отображалась с определением переименования в определенном хранилище, вы можете использовать:

git config diff.renames 1

Файлы , перемещающиеся из одной директории в другую будет обнаружен. Вот пример:

commit c3ee8dfb01e357eba1ab18003be1490a46325992
Author: John S. Gruber <JohnSGruber@gmail.com>
Date:   Wed Feb 22 22:20:19 2017 -0500

    test rename again

diff --git a/yyy/power.py b/zzz/power.py
similarity index 100%
rename from yyy/power.py
rename to zzz/power.py

commit ae181377154eca800832087500c258a20c95d1c3
Author: John S. Gruber <JohnSGruber@gmail.com>
Date:   Wed Feb 22 22:19:17 2017 -0500

    rename test

diff --git a/power.py b/yyy/power.py
similarity index 100%
rename from power.py
rename to yyy/power.py

Обратите внимание, что это работает всякий раз, когда вы используете diff, а не только с git log. Например:

$ git diff HEAD c3ee8df
diff --git a/power.py b/zzz/power.py
similarity index 100%
rename from power.py
rename to zzz/power.py

В качестве пробной версии я внес небольшое изменение в один файл в ветви функций и зафиксировал его, а затем в основной ветви переименовал файл, зафиксировал его, а затем внес небольшое изменение в другую часть файла и зафиксировал его. Когда я пошел в ветку Feature и слился с master, слияние переименовало файл и объединило изменения. Вот вывод из слияния:

 $ git merge -v master
 Auto-merging single
 Merge made by the 'recursive' strategy.
  one => single | 4 ++++
  1 file changed, 4 insertions(+)
  rename one => single (67%)

В результате получился рабочий каталог с переименованным файлом и обоими текстовыми изменениями. Так что Git может делать правильные вещи, несмотря на то, что он явно не отслеживает переименования.

Это поздний ответ на старый вопрос, поэтому другие ответы могли быть верными для версии Git в то время.

Джон С. Грубер
источник
1

Сначала создайте автономный коммит, просто переименовав его.

Затем любые возможные изменения содержимого файла помещаются в отдельный коммит.

Якуб Павловский
источник
1

Чтобы переименовать каталог или файл (я не знаю много о сложных случаях, поэтому могут быть некоторые предупреждения):

git filter-repo --path-rename OLD_NAME:NEW_NAME

Чтобы переименовать каталог в файлах, которые его упоминают (можно использовать обратные вызовы, но я не знаю как):

git filter-repo --replace-text expressions.txt

expressions.txtэто файл, заполненный такими строками, как literal:OLD_NAME==>NEW_NAME(можно использовать RE Python с regex:или глобус с glob:).

Чтобы переименовать каталог в сообщениях о коммитах:

git-filter-repo --message-callback 'return message.replace(b"OLD_NAME", b"NEW_NAME")'

Регулярные выражения Python также поддерживаются, но они должны быть написаны на Python, вручную.

Если репозиторий оригинальный, без пульта, вам придется добавить --force чтобы принудительно переписать. (Вы можете создать резервную копию вашего хранилища, прежде чем делать это.)

Если вы не хотите сохранять ссылки (они будут отображаться в истории веток Git GUI), вам придется добавить --replace-refs delete-no-add.

Пагсли
источник
0

Просто переместите файл и выполните следующие действия :

git add .

Перед фиксацией вы можете проверить статус:

git status

Это покажет:

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    old-folder/file.txt -> new-folder/file.txt

Я тестировал с Git версии 2.26.1.

Извлечено из справочной страницы GitHub .

юниор
источник
-3

Я делаю перемещение файлов, а затем делаю

git add -A

которые помещают в зону сателлита все удаленные / новые файлы. Здесь git понимает, что файл перемещен.

git commit -m "my message"
git push

Я не знаю почему, но это работает для меня.

Xelian
источник
Хитрость в том, что вам не нужно менять одну букву, даже если вы что-то измените и нажмете Ctrl + Z, история будет нарушена. В таком случае, если вы что-то напишите, верните файл, а затем переместите его еще раз и сделайте для него один add-> commit.
Кселиан,