Size verilen tavsiyeler kusurludur. Koşulsuz olarak GIT_AUTHOR_DATE değerini bir olarak ayarlamak --env-filter
her taahhüt tarihini yeniden yazar. Ayrıca, git taahhüdü içeride kullanmak olağandışı olurdu --index-filter
.
Burada birden çok bağımsız sorunla uğraşıyorsunuz.
"Şimdi" Dışındaki Tarihleri Belirtme
Her bir taahhüdün iki tarihi vardır: yazar tarihi ve geçiş tarihi. Yeni bir tamamlama yazan herhangi bir komut için GIT_AUTHOR_DATE ve GIT_COMMITTER_DATE ortam değişkenleri aracılığıyla değerler sağlayarak her birini geçersiz kılabilirsiniz. Git-commit (1) veya aşağısında “Tarih Biçimleri” konusuna bakın:
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
Normal kullanım sırasında yeni bir komut yazan tek komut git command'dur . Ayrıca --date
, yazar tarihini doğrudan belirlemenizi sağlayan bir seçenek de vardır . Öngörülen kullanımınız git filter-branch --env-filter
yukarıda belirtilen ortam değişkenlerini de içerir (bunlar seçeneğin adlandırıldığı “env” nin bir parçasıdır; git-filter-branşında (1) “Seçenekler” ve temel “sıhhi tesisat” komutuna git-commit bakın ağaç (1) .
Dosyayı Tek Bir Ref Geçmişine Ekleme
Deponuz çok basitse (yani yalnızca tek bir dalınız, etiketiniz yoksa), işi yapmak için git rebase'i kullanabilirsiniz .
Aşağıdaki komutlarda, “A” yerine komutun nesne adını (SHA-1 karması) kullanın. Git commit komutunu çalıştırdığınızda “tarih geçersiz kılma” yöntemlerinden birini kullanmayı unutmayın .
---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
A'yı yeni dosyayı içerecek şekilde güncellemek istiyorsanız (eklendiği yerde yeni bir taahhüt oluşturmak yerine) git commit --amend
yerine kullanın git commit
. Sonuç şöyle görünecektir:
---A'---B'---C'---o---o---o master
Yukarıdakiler, yeni taahhüdünüzün ebeveyni olması gereken taahhüdü adlandırabildiğiniz sürece çalışır. Yeni dosyanızın yeni bir root komutu aracılığıyla eklenmesini istiyorsanız (ebeveyn yok), o zaman biraz farklı bir şeye ihtiyacınız vardır:
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
nispeten yeni (Git 1.7.2), ancak Git'in eski sürümlerinde çalışan aynı şeyi yapmanın başka yolları da var .
Çok Referanslı Geçmişe Dosya Ekleme
Deponuz daha karmaşıksa (yani birden fazla ref (dallar, etiketler vb.) Varsa), muhtemelen git filter-branch kullanmanız gerekecektir . Git filtre-dalını kullanmadan önce , tüm deponuzun bir yedek kopyasını almalısınız. Tüm çalışma ağacınızın (.git dizini dahil) basit bir katran arşivi yeterlidir. git filter-branch yedekleme referansları yapar, ancak .git
dizininizi silerek ve yedeklemenizden geri yükleyerek doğru olmayan bir filtreden kurtulmak genellikle daha kolaydır .
Not: Aşağıdaki örnekler git update-index --add
yerine alt düzey komutunu kullanır git add
. Git add'i kullanabilirsiniz , ancak önce dosyayı harici bir konumdan beklenen yola kopyalamanız gerekir ( --index-filter
komutunu boş olan geçici bir GIT_WORK_TREE içinde çalıştırır).
Yeni dosyanızın varolan her işleme eklenmesini istiyorsanız, bunu yapabilirsiniz:
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
Mevcut taahhütlerin tarihlerini değiştirmek için gerçekten bir neden görmüyorum --env-filter 'GIT_AUTHOR_DATE=…'
. Eğer kullansaydınız, şartlı hale getirmelisiniz ki her taahhüt için tarihi yeniden yazsın.
Yeni dosyanızın yalnızca varolan bir işlemden sonra (“A”) yalnızca taahhütlerde görünmesini istiyorsanız, bunu yapabilirsiniz:
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
Dosyanın geçmişinizin ortasına eklenecek yeni bir komutla eklenmesini istiyorsanız, git filter-branch'ı kullanmadan önce yeni bir komut oluşturmanız ve git filter- branch'a eklemeniz --parent-filter
gerekir :
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
Ayrıca dosyanın ilk olarak yeni bir root komutuna eklenmesini de ayarlayabilirsiniz: git rebase bölümünden “yetim” yöntemiyle yeni root komutunuzu oluşturun (yakalayın new_commit
), koşulsuz kullanın --index-filter
ve --parent-filter
benzerlerini yapın "sed -e \"s/^$/-p $new_commit/\""
.