Deleted: * * * * * *
Tags: R S T U V W
Commits: A -> B -> C -> D -> E -> F -> G -> H -> I -> J -> K -> L -> M -> N
預期輸出:
Tags: R T V W
Commits: A -> B -> E -> G -> H -> I -> L -> N
我們將與--prune-empty
所以我們正在創造空提交對應該將其刪除的提交可以測試這個。我們來設置測試存儲庫。
git init
touch n && git add n && git commit -m "N"
git commit --allow-empty -m "M"
touch l && git add l && git commit -m "L"
git commit --allow-empty -m "K"
git commit --allow-empty -m "J"
touch i && git add i && git commit -m "I"
touch h && git add h && git commit -m "H"
touch g && git add g && git commit -m "G"
git commit --allow-empty -m "F"
touch e && git add e && git commit -m "E"
git commit --allow-empty -m "D"
git commit --allow-empty -m "C"
touch b && git add b && git commit -m "B"
touch a && git add a && git commit -m "A"
git tag W $(git log --pretty=oneline --grep=M | cut -d " " -f1)
git tag V $(git log --pretty=oneline --grep=K | cut -d " " -f1)
git tag U $(git log --pretty=oneline --grep=F | cut -d " " -f1)
git tag T $(git log --pretty=oneline --grep=E | cut -d " " -f1)
git tag S $(git log --pretty=oneline --grep=D | cut -d " " -f1)
git tag R $(git log --pretty=oneline --grep=C | cut -d " " -f1)
首先我們要創建一個文件,其中包含所有標記名稱以及它們指向的提交哈希。
for i in $(git tag); do echo $i; git log -1 --pretty=oneline $i | cut -d " " -f1; done > ../tags
當運行git filter-branch
提交哈希將改變。爲了跟蹤這些變化,我們創建一個文件,其中包含從舊提交哈希到新提交哈希的映射。這樣做的訣竅顯示爲here。
的--subdirectory-filter=...
命令會再看看這樣的:
git filter-branch --subdirectory-filter=... --commit-filter 'echo -n "${GIT_COMMIT}," >>/tmp/commap; git commit-tree "[email protected]" | tee -a /tmp/commap'
因爲有我們需要改變某些事情了--commit-filter
的--prune-empty
選項衝突。的--prune-empty
文檔在這裏幫助:
有些過濾器會產生離開樹觸及空的提交。這個選項指示git-filter-branch刪除這樣的提交,如果它們只有一個或零個未修剪的父母;因此合併提交將保持不變。此選項不能與--commit-filter
一起使用,但通過在提交過濾器中使用提供的git_commit_non_empty_tree
函數可以實現相同的效果。
因此,我們將用於此測試的--prune-empty
命令如下所示。在運行該命令之前,確保/tmp/commap
不存在或爲空。
git filter-branch --commit-filter 'echo -n "${GIT_COMMIT}," >>/tmp/commap; git_commit_non_empty_tree "[email protected]" | tee -a /tmp/commap'
mv /tmp/commap ../commap
現在我們跑git filter-branch
並收集應對標籤所需的所有信息。我們將不得不刪除標籤,我們將不得不更改提交標籤。我們在這裏很幸運,git只是在.git/refs/tags/TAGNAME
中存儲了提交散列標記。
現在剩下的是寫一個腳本來自動更正標籤。這是我用Python寫的。
def delete(tagname):
print('git tag -d {}'.format(tagname))
def move(tagname, tagref):
print('echo "{}" > .git/refs/tags/{}'.format(tagref, tagname))
tags = {}
with open('tags') as tagsfile:
for i, line in enumerate(tagsfile):
if i%2 == 0:
tagname = line[:-1]
else:
# if there are multiple tags on one commit
# we discard all but one
tagref = line[:-1]
if tagref in tags:
delete(tags[tagref])
tags[tagref] = tagname
commap = []
with open('commap') as commapfile:
for line in commapfile:
old, new = line[:-1].split(',')
commap.append((old, new))
lastnew = None
takentag = None
for old, new in commap:
if old in tags:
if takentag:
delete(takentag)
takentag = tags[old]
if new != lastnew:
# commit was not deleted
if takentag:
move(takentag, new)
takentag = None
lastnew = new
該腳本輸出調整標籤所需的命令。在我們的例子是這樣的輸出:
echo "0593fe3aa7a50d41602697f51f800d34b9887ba3" > .git/refs/tags/W
echo "93e65edf18ec8e33e5cc048e87f8a9c5270dd095" > .git/refs/tags/V
git tag -d U
echo "41d9e45de069df2c8f2fdf9ba1d2a8b3801e49b2" > .git/refs/tags/T
git tag -d S
echo "a0c4c919f841295cfdb536fcf8f7d50227e8f062" > .git/refs/tags/R
粘貼命令Git倉庫看起來如預期控制檯後:
$ git log
8945e933c1d8841ffee9e0bca1af1fce84c2977d A
a0c4c919f841295cfdb536fcf8f7d50227e8f062 B
41d9e45de069df2c8f2fdf9ba1d2a8b3801e49b2 E
6af1365157d705bff79e8c024df544fcd24371bb G
108ddf9f5f0a8c8d1e17042422fdffeb147361f2 H
93e65edf18ec8e33e5cc048e87f8a9c5270dd095 I
0593fe3aa7a50d41602697f51f800d34b9887ba3 L
5200d5046bc92f4dbe2aee4d24637655f2af5d62 N
$ git tag
R
T
V
W
$ git log -1 --pretty=oneline R
a0c4c919f841295cfdb536fcf8f7d50227e8f062 B
$ git log -1 --pretty=oneline T
41d9e45de069df2c8f2fdf9ba1d2a8b3801e49b2 E
$ git log -1 --pretty=oneline V
93e65edf18ec8e33e5cc048e87f8a9c5270dd095 I
$ git log -1 --pretty=oneline W
0593fe3aa7a50d41602697f51f800d34b9887ba3 L
嗨,剛開始賞金的寬限期,想獲得它。我只是想提醒你,以防第一次通知/電子郵件丟失。 – timakro
@timakro對不起,但:您認爲哪個寬限期?我不記得設立了一個賞金..但呢?! –
其他人設置賞金,但它現在跑了^^。沒關係,但不是你的錯。 – timakro