Jak zrobić commit Git w przeszłości?
Konwertuję wszystko na Gita na własny użytek i znalazłem kilka starych wersji pliku już w repozytorium. Jak dodać go do historii w odpowiedniej kolejności zgodnie z "datą modyfikacji" pliku, aby mieć dokładną historię pliku?
Powiedziano mi, że coś takiego zadziała:
git filter-branch --env-filter="GIT_AUTHOR_DATE=... --index-filter "git commit path/to/file --date " --tag-name-filter cat -- --all
7 answers
Twoja rada jest błędna. Bezwarunkowo ustawienie GIT_AUTHOR_DATE w --env-filter
zmieniłoby datę każdego commita. Ponadto, nietypowe byłoby użycie git commit wewnątrz --index-filter
.
Określanie dat innych niż"teraz"
Każdy commit ma dwie daty: datę autora i datę zatwierdzenia. Możesz nadpisać każdą z nich, dostarczając wartości za pomocą zmiennych środowiskowych GIT_AUTHOR_DATE i GIT_COMMITTER_DATE dla każdego polecenia, które pisze nowy commit. Zobacz "formaty daty" w git-commit (1) lub poniżej:
Git internal format = <unix timestamp> <time zone offset>, e.g. 1112926393 +0200
RFC 2822 = e.g. Thu, 07 Apr 2005 22:13:13 +0200
ISO 8601 = e.g. 2005-04-07T22:13:13
Jedynym poleceniem, które pisze nowy commit podczas normalnego użytkowania jest git commit. Posiada również opcję --date
, która pozwala bezpośrednio określić datę autora. Twoje przewidywane użycie zawiera git filter-branch --env-filter
również używa zmiennych środowiskowych wymienionych powyżej (są one częścią "env", po którym opcja jest nazwana; zobacz "opcje" w git-filter-branch(1) oraz podstawowe polecenie "plumbing" git-commit-tree(1).
Wstawianie pliku do pojedynczego ref Historia
Jeśli Twoje repozytorium jest bardzo proste (tzn. masz tylko jedną gałąź, bez znaczników), to prawdopodobnie możesz użyć git rebase do wykonania tej pracy.
W poniższych poleceniach użyj nazwy obiektu (SHA-1 hash) zatwierdzania zamiast "A". Nie zapomnij użyć jednej z metod "nadpisania daty" podczas uruchamiania git commit.
---A---B---C---o---o---o master
git checkout master
git checkout A~0
git add path/to/file
git commit --date='whenever'
git tag ,new-commit -m'delete me later'
git checkout -
git rebase --onto ,new-commit A
git tag -d ,new-commit
---A---N (was ",new-commit", but we delete the tag)
\
B'---C'---o---o---o master
Jeśli chcesz zaktualizować a, aby zawierał nowy plik (zamiast tworzyć nowy commit, w którym został dodany), użyj git commit --amend
zamiast git commit
. Wynik wyglądałby tak:
---A'---B'---C'---o---o---o master
Powyższe działanie działa tak długo, jak długo możesz nazwać commit, który powinien być rodzicem twojego nowego commita. Jeśli chcesz, aby nowy plik został dodany przez nowy commit główny( bez rodziców), potrzebujesz czegoś nieco innego: {]}
B---C---o---o---o master
git checkout master
git checkout --orphan new-root
git rm -rf .
git add path/to/file
GIT_AUTHOR_DATE='whenever' git commit
git checkout -
git rebase --root --onto new-root
git branch -d new-root
N (was new-root, but we deleted it)
\
B'---C'---o---o---o master
git checkout --orphan
jest stosunkowo nowy (Git 1.7.2), ale istnieją inne sposoby robienia tego samego , które działają na starszych wersjach Gita.
Wstawianie pliku do Multi-ref Historia
Jeśli Twoje repozytorium jest bardziej złożone (tzn. ma więcej niż jeden ref (gałęzie, znaczniki itp.)), wtedy prawdopodobnie będziesz musiał użyć git filter-branch. przed użyciem git filter-branch , należy wykonać kopię zapasową całego repozytorium.a simple tar archiwum całego drzewa roboczego (w tymGit directory) jest wystarczający. git filter-branch robi kopie zapasowe refs, ale często łatwiej jest odzyskać kopię z nie do końca odpowiedniego filtrowania, usuwając katalog .git
i przywracając go z kopii zapasowej.
Uwaga: poniższe przykłady używają polecenia niższego poziomu git update-index --add
zamiast git add
. Możesz użyć git add, ale najpierw musisz skopiować plik z jakiejś zewnętrznej lokalizacji do oczekiwanej ścieżki (--index-filter
uruchamia jego polecenie w tymczasowym GIT_WORK_TREE, które jest puste).
Jeśli chcesz, aby Twój nowy plik był dodawany do każdego istniejącego commita, możesz to zrobić:
new_file=$(git hash-object -w path/to/file)
git filter-branch \
--index-filter \
'git update-index --add --cacheinfo 100644 '"$new_file"' path/to/file' \
--tag-name-filter cat \
-- --all
git reset --hard
Nie widzę powodu, aby zmieniać daty istniejących commitów za pomocą --env-filter 'GIT_AUTHOR_DATE=…'
. Gdybyś go użył, zmieniłbyś datę każdego commita.
Jeśli chcesz, aby nowy plik pojawiał się tylko w zatwierdzeniu po jakimś istniejącym zatwierdzeniu ("A"), możesz to zrobić to:
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
file_blob=$(git hash-object -w "$file_path")
git filter-branch \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$before_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
Jeśli chcesz, aby plik został dodany przez nowy commit, który ma zostać wstawiony do środka twojej historii, musisz wygenerować nowy commit przed użyciem git filter-branch i dodać --parent-filter
do git filter-branch :
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
git checkout master
git checkout "$before_commit"
git add "$file_path"
git commit --date='whenever'
new_commit=$(git rev-parse --verify HEAD)
file_blob=$(git rev-parse --verify HEAD:"$file_path")
git checkout -
git filter-branch \
--parent-filter "sed -e s/$before_commit/$new_commit/g" \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$new_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
Możesz również zaaranżować, aby plik został dodany jako pierwszy w nowym commicie root: utwórz nowy commit root za pomocą metody" orphan " z sekcji Git rebase (przechwyć go w new_commit
), użyj bezwarunkowa --index-filter
, a --parent-filter
Jak "sed -e \"s/^$/-p $new_commit/\""
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-18 18:24:18
Możesz utworzyć commit jak zwykle, ale po zatwierdzeniu Ustaw zmienne środowiskowe GIT_AUTHOR_DATE
i GIT_COMMITTER_DATE
na odpowiednie okresy.
Oczywiście spowoduje to, że commit pojawi się na końcu twojej gałęzi (tj. przed aktualnym commitem głównym). Jeśli chcesz przesunąć go dalej w repo, musisz się trochę wykwintnie. Powiedzmy, że masz tę historię:
o--o--o--o--o
I chcesz, aby nowy commit (oznaczony jako "X") pojawił się second :
o--X--o--o--o--o
Najprostszy sposób będzie branch z pierwszego commita, Dodaj nowy commit, a następnie zmień wszystkie inne commity na nowe. Tak:
$ git checkout -b new_commit $desired_parent_of_new_commit
$ git add new_file
$ GIT_AUTHOR_DATE='your date' GIT_COMMITTER_DATE='your date' git commit -m 'new (old) files'
$ git checkout master
$ git rebase new_commit
$ git branch -d new_commit
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-09 15:16:12
Wiem, że to pytanie jest dość stare, ale to właśnie na mnie zadziałało:
git commit --date="10 day ago" -m "Your commit message"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-09 19:31:48
W moim przypadku z czasem zapisałem kilka wersji myfile jako myfile_bak, myfile_old, myfile_2010, backups/myfile itp. Chciałem umieścić historię myfile w git używając ich dat modyfikacji. Więc zmień nazwę najstarszego na myfile, git add myfile
, następnie git commit --date=(modification date from ls -l) myfile
, Zmień nazwę następnego najstarszego na myfile, kolejny commit z --date, repeat...
Aby to nieco zautomatyzować, możesz użyć shell-foo, aby uzyskać czas modyfikacji pliku. Zacząłem od ls -l
i cut
, ale stat (1) jest bardziej bezpośrednie
git commit --date="`stat -c %y myfile`" myfile
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-14 19:20:38
W moim przypadku, podczas używania opcji --date, mój proces git uległ awarii. Może zrobiłem coś strasznego. I w rezultacie jakiś indeks.pojawił się plik blokady. Więc ręcznie usunięte .Zablokuj pliki z .git folder i wykonane, dla wszystkich zmodyfikowanych plików, które mają być committed w mijanych datach i to działało tym razem. Thanx za wszystkie odpowiedzi tutaj.
git commit --date="`date --date='2 day ago'`" -am "update"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-30 11:03:45
Oto, czego używam do zatwierdzania zmian w foo
na N=1
dni w przeszłości:
git add foo
git commit -m "Update foo"
git commit --amend --date="$(date -v-1d)"
Jeśli chcesz zobowiązać się do jeszcze starszej daty, powiedzmy 3 dni wstecz, po prostu zmień argument date
: date -v-3d
.
To naprawdę przydatne, gdy zapomnisz coś wczoraj popełnić, na przykład.
Aktualizacja: --date
akceptuje również wyrażenia typu --date "3 days ago"
lub nawet --date "yesterday"
. Możemy więc zredukować ją do jednej komendy liniowej:
git add foo ; git commit --date "yesterday" -m "Update"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 13:43:38
Zawsze możesz zmienić datę na swoim komputerze, wprowadzić commit, następnie zmienić datę wstecz i wcisnąć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-27 10:31:52