Я конвертирую все в Git для личного использования, и я нашел несколько старых версий файла, уже находящихся в хранилище. Как передать его в историю в правильном порядке в соответствии с «датой изменения файла», чтобы у меня была точная история файла?
Мне сказали, что-то вроде этого будет работать:
git filter-branch --env-filter="GIT_AUTHOR_DATE=... --index-filter "git commit path/to/file --date " --tag-name-filter cat -- --all
git
version-control
repository
git-commit
неизвестный
источник
источник
git commit --date="xxx day ago" -m "yyy"
для этого достаточно просто настройки , если кому-то интересно.Ответы:
Совет, который вам дали, ошибочен. Безусловно, установка GIT_AUTHOR_DATE в an
--env-filter
переписывает дату каждого коммита. Кроме того, было бы необычно использовать git commit внутри--index-filter
.Вы имеете дело с множеством независимых проблем здесь.
Указание дат, отличных от «сейчас»
Каждый коммит имеет две даты: дату автора и дату коммиттера. Вы можете переопределить каждое из них, указав значения через переменные окружения GIT_AUTHOR_DATE и GIT_COMMITTER_DATE для любой команды, которая записывает новый коммит. Смотрите «Форматы даты» в git-commit (1) или ниже:
Единственная команда, которая записывает новый коммит при обычном использовании, это git commit . Также имеется
--date
опция, позволяющая напрямую указать дату автора. Предполагаемое использование включает в себяgit filter-branch --env-filter
также использование переменных среды, упомянутых выше (они являются частью «env», после которого названа опция; см. «Опции» в git-filter-branch (1) и базовой команде «plumbing» git-commit). -дерево (1) .Вставка файла в историю ссылок
Если ваш репозиторий очень прост (т.е. у вас есть только одна ветвь, без тегов), то вы, вероятно, можете использовать git rebase для выполнения этой работы.
В следующих командах используйте имя объекта (хэш SHA-1) фиксации вместо «A». Не забудьте использовать один из методов «переопределения даты» при запуске git commit .
Если вы хотите обновить A, чтобы включить новый файл (вместо создания нового коммита, где он был добавлен), используйте
git commit --amend
вместоgit commit
. Результат будет выглядеть так:Вышеуказанное работает до тех пор, пока вы можете назвать коммит, который должен быть родителем вашего нового коммита. Если вы действительно хотите, чтобы ваш новый файл был добавлен с помощью нового корневого коммита (без родителей), то вам нужно что-то немного другое:
git checkout --orphan
является относительно новым (Git 1.7.2), но есть и другие способы сделать то же самое, что работает на более старых версиях Git.Вставка файла в историю нескольких ссылок
Если ваш репозиторий более сложный (т. Е. Имеет несколько ссылок (ветки, теги и т. Д.)), То вам, вероятно, потребуется использовать git filter-branch . Перед использованием git filter-branch , вы должны сделать резервную копию всего вашего хранилища. Достаточно простого архива tar всего вашего рабочего дерева (включая каталог .git). git filter-branch делает резервные ссылки, но зачастую проще восстановить не совсем правильную фильтрацию, просто удалив
.git
каталог и восстановив его из резервной копии.Примечание. В приведенных ниже примерах
git update-index --add
вместо команды используется команда более низкого уровняgit add
. Вы можете использовать git add , но сначала вам нужно будет скопировать файл из какого-то внешнего местоположения в ожидаемый путь (--index-filter
его команда запускается во временном пустом GIT_WORK_TREE).Если вы хотите, чтобы ваш новый файл был добавлен в каждый существующий коммит, то вы можете сделать это:
Я не вижу смысла менять даты существующих коммитов
--env-filter 'GIT_AUTHOR_DATE=…'
. Если бы вы использовали его, вы бы сделали его условным, чтобы он переписывал дату для каждого коммита.Если вы хотите, чтобы ваш новый файл появлялся только в коммитах после некоторого существующего коммита («A»), то вы можете сделать это:
Если вы хотите, чтобы файл был добавлен с помощью нового коммита, который должен быть вставлен в середину вашей истории, вам нужно будет сгенерировать новый коммит перед использованием git filter-branch и добавить
--parent-filter
в git filter-branch :Кроме того, можно организовать файл , чтобы быть первым добавлен в новом корне фиксации: создать новый корень совершать через «сиротский» метод из мерзавец Rebase секции (захват его в
new_commit
), использовать безусловный--index-filter
и--parent-filter
как"sed -e \"s/^$/-p $new_commit/\""
.источник
--index-filter
применить к коммитам, возвращеннымgit rev-list
? В данный момент я вижу индексный фильтр, примененный к подмножеству rev-list. Ценю любое понимание.-- --all
для обработки всех коммитов, доступных с любого реф. В последнем примере показано, как изменить только определенные коммиты (просто протестируйте GIT_COMMIT для всего, что вам нравится). Чтобы изменить только определенный список коммитов, вы можете сохранить список перед фильтрацией (напримерgit rev-list … >/tmp/commits_to_rewrite
), а затем проверить его на принадлежность к фильтру (например,if grep -qF "$GIT_COMMIT" /tmp/commits_to_rewrite; then git update-index …
). Что именно вы пытаетесь достичь? Возможно, вы захотите начать новый вопрос, если это слишком много, чтобы объяснить в комментариях.import-directories.perl
из Gitcontrib/
(илиimport-tars.perl
, илиimport-zips.py
...), чтобы создать новый репозиторий Git из ваших снимков (даже с «Старые» временные метки). Вrebase
/filter-branch
методах в моем ответе нужны , только если вы хотите , чтобы вставить файл , который был «левый» из истории существующего хранилища.Вы можете создать коммит как обычно, но когда вы фиксируете, установите переменные среды
GIT_AUTHOR_DATE
иGIT_COMMITTER_DATE
соответствующие даты и время.Конечно, это сделает коммит на кончике вашей ветви (т.е. перед текущим коммитом HEAD). Если вы хотите отодвинуть его дальше в репо, вам нужно немного придумать. Допустим, у вас есть эта история:
И вы хотите, чтобы ваш новый коммит (помеченный как «X») появился вторым :
Самый простой способ - это перейти с первого коммита, добавить новый коммит, а затем перебазировать все остальные коммиты поверх нового. Вот так:
источник
GIT_AUTHOR_DATE='Fri Jul 26 19:32:10 2013 -0400' GIT_COMMITTER_DATE='Fri Jul 26 19:32:10 2013 -0400' git commit
2013-07-26T19:32:10
: kernel.org/pub/software/scm/git/docs/...THE_TIME='2019-03-30T8:20:00 -0500' GIT_AUTHOR_DATE=$THE_TIME GIT_COMMITTER_DATE=$THE_TIME git commit -m 'commit message here'
Я знаю, что этот вопрос довольно старый, но это то, что на самом деле работает для меня:
источник
--date
также поддерживает удобочитаемый формат даты.git --date
только изменит $ GIT_AUTHOR_DATE ... поэтому в зависимости от обстоятельств вы увидите текущую дату, прикрепленную к коммиту ($ GIT_COMMITTER_DATE)git show <commit-hash> --format=fuller
. Там вы увидитеAuthorDate
указанную вами дату, ноCommitDate
фактическую дату принятия.В моем случае со временем я сохранил несколько версий myfile как myfile_bak, myfile_old, myfile_2010, backups / myfile и т. Д. Я хотел поместить историю myfile в git, используя даты их изменения. Так что переименуйте самый старый в myfile,
git add myfile
затемgit commit --date=(modification date from ls -l) myfile
переименуйте следующий самый старый в myfile, еще один git commit с --date, repeat ...Чтобы немного это автоматизировать, вы можете использовать shell-foo, чтобы получить время модификации файла. Я начал с
ls -l
иcut
, но stat (1) является более прямымисточник
--date
«Переопределить дату автора, использованную в коммите ».git log
Дата, похоже, является AuthorDate,git log --pretty=fuller
показывает как AuthorDate, так и CommitDate.git commit
Параметр--date
будет изменять толькоGIT_AUTHOR_DATE
неGIT_COMMITTER_DATE
. Как объясняет Pro Git Book : «Автор - это человек, который изначально написал произведение, а автор, который в последний раз применил это произведение». В контексте дат,GIT_AUTHOR_DATE
это дата, когда файл был изменен, тогда какGIT_COMMITTER_DATE
это дата, когда он был зафиксирован. Здесь важно отметить, что по умолчаниюgit log
даты автора отображаются как «Дата», но затем используются даты фиксации для фильтрации при наличии--since
опции.stat -c %y
в macOS (и других вариантах BSD) естьstat -f %m
.Ниже то , что я использую , чтобы вносить изменения в
foo
вN=1
дни в прошлом:Если вы хотите взять на себя обязательство еще более старую дату, скажем , 3 дня назад, просто изменить
date
аргумент:date -v-3d
.Это действительно полезно, например, если вы забыли что-то сделать вчера.
ОБНОВЛЕНИЕ :
--date
также принимает выражения как--date "3 days ago"
или даже--date "yesterday"
. Таким образом, мы можем сократить его до одной строковой команды:источник
git --date
будет изменяться только $ GIT_AUTHOR_DATE ... поэтому в зависимости от обстоятельств вы увидите текущую дату, прикрепленную к коммиту ($ GIT_COMMITTER_DATE)git commit --amend --date="$(stat -c %y fileToCopyMTimeFrom)"
git commit --amend --date="$(date -R -d '2020-06-15 16:31')"
В моем случае при использовании параметра --date мой процесс git потерпел крах. Может быть, я сделал что-то ужасное. И в результате появился файл index.lock. Поэтому я вручную удалил файлы .lock из папки .git и выполнил их, чтобы все измененные файлы были переданы в прошедшие даты, и на этот раз это сработало. Спасибо за все ответы здесь.
источник
git commit --date
. Кроме того , ваш пример сообщения о фиксации должны быть внесены изменения , чтобы препятствовать плохие сообщения однострочные , как эти @JstRoRRgit --date
только изменит $ GIT_AUTHOR_DATE ... поэтому в зависимости от обстоятельств вы увидите текущую дату, прикрепленную к коммиту ($ GIT_COMMITTER_DATE)Чтобы сделать коммит, который выглядит так, как будто это было сделано в прошлом, вы должны установить
GIT_AUTHOR_DATE
иGIT_COMMITTER_DATE
:где
date -d'...'
может быть точная дата как2019-01-01 12:00:00
или относительная как5 months ago 24 days ago
.Чтобы увидеть обе даты в git log, используйте:
Это также работает для коммитов слияния:
источник
Вы всегда можете изменить дату на своем компьютере, сделать коммит, а затем изменить дату назад и нажать.
источник
Или просто используйте fake-git-history, чтобы сгенерировать ее для определенного диапазона данных.
источник