Я хотел бы переименовать / переместить поддерево проекта в Git, перемещая его из
/project/xyz
в
/components/xyz
Если я использую равнину git mv project components
, то вся история коммитов xyz project
теряется. Есть ли способ переместить это так, чтобы история сохранялась?
git mv
: stackoverflow.com/questions/1094269/whats-the-purpose-of-git-mvОтветы:
Git обнаруживает переименования, а не сохраняет операцию с фиксацией, поэтому, используете ли вы
git mv
илиmv
не имеет значения.Команда
log
принимает--follow
аргумент, который продолжает историю до операции переименования, т. Е. Ищет похожий контент, используя эвристику:http://git-scm.com/docs/git-log
Чтобы просмотреть полную историю, используйте следующую команду:
источник
git config alias.logf "log --follow"
и просто написатьgit logf ./path/to/file
.Это можно переименовать файл и сохранить историю нетронутым, хотя это приводит к тому , файл будет переименован в течение всей истории репозитория. Это, вероятно, только для навязчивых любителей git-log, и имеет некоторые серьезные последствия, включая следующие:
Теперь, так как вы все еще со мной, вы, вероятно, одинокий разработчик, переименовывающий полностью изолированный файл. Давайте переместим файл используя
filter-tree
!Предположим, вы собираетесь переместить файл
old
в папкуdir
и дать ему имяnew
Это может быть сделано
git mv old dir/new && git add -u dir/new
, но это ломает историю.Вместо:
будет повторять каждый коммит в ветви, выполняя команду в тиках для каждой итерации. Много вещей может пойти не так, когда вы сделаете это. Обычно я проверяю, присутствует ли файл (в противном случае он еще не перемещен), а затем выполняю необходимые шаги, чтобы подковать дерево по своему вкусу. Здесь вы можете просматривать файлы для изменения ссылок на файл и так далее. Сбей себя с ног! :)
По завершении файл перемещается, а журнал не изменяется. Вы чувствуете себя пиратом ниндзя.
Также; Разумеется, каталог mkdir необходим только в том случае, если вы перемещаете файл в новую папку. , Если будет избегать создания этой папки ранее в истории , чем существует файл.
источник
--index-filter
переименований будет намного быстрее, поскольку дерево не нужно извлекать и возвращать при каждом коммите.--index-filter
действует непосредственно на каждый индекс коммита.Нет.
Краткий ответ - НЕТ . Невозможно переименовать файл в Git и запомнить историю. И это боль.
Ходят слухи, что
git log --follow
--find-copies-harder
это сработает, но у меня это не сработает, даже если в содержании файла нет нулевых изменений, а ходы были сделаныgit mv
.(Изначально я использовал Eclipse для переименования и обновления пакетов в одной операции, что может сбить Git с толку. Но это очень распространенная вещь.
--follow
Похоже, работает, еслиmv
выполняется только a, а затем acommit
и themv
не слишком далеко.)Линус говорит, что вы должны понимать все содержимое программного проекта в целом, без необходимости отслеживать отдельные файлы. Ну, к сожалению, мой маленький мозг не может этого сделать.
Это действительно раздражает , что так много людей бездумно повторил заявление , что Git автоматически отслеживает движения. Они потратили впустую мое время. Git не делает таких вещей. По замыслу (!) Git вообще не отслеживает ходы.
Мое решение состоит в том, чтобы переименовать файлы обратно в их исходные места. Измените программное обеспечение в соответствии с контролем источника. С Git вам, кажется, просто нужно «сделать» это правильно с первого раза.
К сожалению, это нарушает Eclipse, который, кажется, использует
--follow
.git log --follow
иногда не показывает полную историю файлов со сложной историей переименования, хотя иgit log
делает. (Я не знаю, почему.)(Есть некоторые слишком умные хаки, которые возвращаются и возобновляют старую работу, но они довольно пугающие. См. GitHub-Gist: emiller / git-mv-with-history .)
источник
покажет вам историю через переименования.
источник
git mv
основном делаетgit rm && git add
. Есть варианты, такие как-M90
/,--find-renames=90
чтобы считать файл переименованным, когда он на 90% идентичен.Я делаю:
источник
-A
вместо? Опять же, смотрите здесь: git-scm.com/docs/git-addgit add -u
. Документы Git, как правило, бесполезны и являются последним местом, которое я бы хотел посмотреть. Вот один пост, показывающийgit add -u
в действии: stackoverflow.com/a/2117202 .Нет (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
:Пример:
Но они много других случаев, таких как:
Чтобы упростить обнаружение переименования каталогов, эти правила применяются Git:
ограничение пары основных правил, когда применяется обнаружение переименования каталогов:
Вы можете увидеть множество тестов
t/t6043-merge-rename-directories.sh
, которые также указывают, что:источник
Задача
git am
ограничение
Резюме
git log --pretty=email -p --reverse --full-index --binary
cat extracted-history | git am --committer-date-is-author-date
1. Извлечь историю в формате электронной почты
Пример: история Экстракт
file3
,file4
иfile5
Установить / очистить пункт назначения
Извлечь историю каждого файла в формате электронной почты
К сожалению вариант
--follow
или--find-copies-harder
нельзя сочетать с--reverse
. Вот почему история обрезается при переименовании файла (или при переименовании родительского каталога).Временная история в формате электронной почты:
Дэн Бонэйча предлагает инвертировать циклы команды генерации git log на этом первом шаге: вместо того, чтобы запускать git log один раз для каждого файла, запускайте его ровно один раз со списком файлов в командной строке и генерируйте единый объединенный журнал. Таким образом, коммиты, которые изменяют несколько файлов, остаются в результате одним коммитом, и все новые коммиты сохраняют свой первоначальный относительный порядок. Обратите внимание, что это также требует изменений на втором этапе ниже при перезаписи имен файлов в (теперь объединенном) журнале.
2. Реорганизовать дерево файлов и обновить имена файлов
Предположим, вы хотите переместить эти три файла в этом другом репо (это может быть тот же репо).
Поэтому реорганизуйте ваши файлы:
Ваша временная история сейчас:
Измените также имена файлов в истории:
3. Применить новую историю
Ваш другой репо:
Применить коммиты из временных файлов истории:
--committer-date-is-author-date
сохраняет оригинальные отметки времени коммита ( комментарий Дана Боначи ).Ваш другой репо сейчас:
Используйте,
git status
чтобы увидеть количество коммитов, готовых к отправке :-)Дополнительный трюк: проверка переименованных / перемещенных файлов в вашем репо
Для просмотра списка файлов, которые были переименованы:
Дополнительные настройки: вы можете выполнить команду,
git log
используя параметры--find-copies-harder
или--reverse
. Вы также можете удалить первые два столбца, используяcut -f3-
полный шаблон '{. * =>. *}'.источник
Я следовал этому многоэтапному процессу, чтобы переместить код в родительский каталог и сохранить историю.
Шаг 0: создал ветку 'history' из 'master' для безопасного хранения
Шаг 1: Использовал инструмент git-filter-repo для переписывания истории. Эта команда ниже переместила папку «FolderwithContentOfInterest» на один уровень вверх и изменила соответствующую историю изменений
Шаг 2: К этому времени репозиторий GitHub потерял свой путь к удаленному репозиторию. Добавлена удаленная ссылка
Шаг 3: Извлечь информацию из хранилища
Шаг 4: Соедините локальную потерянную ветку с исходной веткой
Шаг 5: конфликт слияния адресов для структуры папок, если будет предложено
Шаг 6: Нажмите !!
Примечание. Измененная история и перемещенная папка уже зафиксированы.
enter code here
Выполнено. Код перемещается в родительский / нужный каталог, сохраняя историю нетронутой!
источник
В то время как ядро Git, сантехника Git не отслеживает переименования, история, которую вы отображаете с помощью «фарфора» журнала Git, может обнаружить их, если хотите.
Для данного
git log
использования используйте опцию -M:С текущей версией Git.
Это работает и для других команд
git diff
.Есть варианты сделать сравнения более или менее строгими. Если вы переименуете файл, не внося при этом значительных изменений в файл, то для журнала Git и его друзей будет легче обнаружить переименование. По этой причине некоторые люди переименовывают файлы в одном коммите и изменяют их в другом.
Использование ЦП требует затрат, когда вы спрашиваете Git, где найти файлы, которые были переименованы, независимо от того, используете ли вы их или нет, и когда, решать только вам.
Если вы хотите, чтобы ваша история всегда отображалась с определением переименования в определенном хранилище, вы можете использовать:
Файлы , перемещающиеся из одной директории в другую будет обнаружен. Вот пример:
Обратите внимание, что это работает всякий раз, когда вы используете diff, а не только с
git log
. Например:В качестве пробной версии я внес небольшое изменение в один файл в ветви функций и зафиксировал его, а затем в основной ветви переименовал файл, зафиксировал его, а затем внес небольшое изменение в другую часть файла и зафиксировал его. Когда я пошел в ветку Feature и слился с master, слияние переименовало файл и объединило изменения. Вот вывод из слияния:
В результате получился рабочий каталог с переименованным файлом и обоими текстовыми изменениями. Так что Git может делать правильные вещи, несмотря на то, что он явно не отслеживает переименования.
Это поздний ответ на старый вопрос, поэтому другие ответы могли быть верными для версии Git в то время.
источник
Сначала создайте автономный коммит, просто переименовав его.
Затем любые возможные изменения содержимого файла помещаются в отдельный коммит.
источник
Чтобы переименовать каталог или файл (я не знаю много о сложных случаях, поэтому могут быть некоторые предупреждения):
Чтобы переименовать каталог в файлах, которые его упоминают (можно использовать обратные вызовы, но я не знаю как):
expressions.txt
это файл, заполненный такими строками, какliteral:OLD_NAME==>NEW_NAME
(можно использовать RE Python сregex:
или глобус сglob:
).Чтобы переименовать каталог в сообщениях о коммитах:
Регулярные выражения Python также поддерживаются, но они должны быть написаны на Python, вручную.
Если репозиторий оригинальный, без пульта, вам придется добавить
--force
чтобы принудительно переписать. (Вы можете создать резервную копию вашего хранилища, прежде чем делать это.)Если вы не хотите сохранять ссылки (они будут отображаться в истории веток Git GUI), вам придется добавить
--replace-refs delete-no-add
.источник
Просто переместите файл и выполните следующие действия :
Перед фиксацией вы можете проверить статус:
Это покажет:
Я тестировал с Git версии 2.26.1.
Извлечено из справочной страницы GitHub .
источник
Я делаю перемещение файлов, а затем делаю
которые помещают в зону сателлита все удаленные / новые файлы. Здесь git понимает, что файл перемещен.
Я не знаю почему, но это работает для меня.
источник