[英]filter-branch that includes all commits of renamed files
使用此處說明的filter-branch
,可以將某些子目錄拆分到新的存儲庫中。 但是,建議的過濾器將僅保留目錄中文件具有與現在相同名稱/路徑的提交。
git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME
我需要一個過濾器,該過濾器將使每個文件的提交與執行gitk --follow FILE-NAME
時的提交相同。
本質上,我需要一個過濾器,該過濾器將保留目錄中每個文件的當前文件名/路徑和舊文件名/路徑的提交。
我試過了:
git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- FOLDER-NAME' --prune-empty -- --all
但是它和--subdirectory-filter
。
您將必須編寫自己的,花哨的(也許非常花哨的)過濾器。
我的意思不是修改git filter-branch
來添加一個新的--EJS-filter
。 這將是做到這一點的一種方式,但會要求你可笑幻想。 :-)相反,我的意思是:
找到您要保留的特定提交范圍內的名稱。
這可能相對容易:從a123456
之后的“提交”開始,保留所有名為newdirname/*
文件,從a123456
“ before” a123456
(包括a123456
本身),則保留所有名為olddirname/*
文件。
這甚至可能非常容易:也許在a123456
之后的a123456
, 沒有名為olddirname/*
文件 ,並且在此之前的提交中,沒有名為newdirname/*
文件。 在這種情況下,您的過濾器將olddirname/*
為: 保留所有名為olddirname/*
或newdirname/*
; 刪除所有其他文件。
如果不是那么容易,那么那就不是那么容易。
現在,您已經確定了要保留的文件,編寫一個--tree-filter
(很慢,但是很容易編寫)或--index-filter
(要快得多,但是很難編寫),以保留您想要的文件並刪除不需要的文件。
在這里,您可以(也許必須)利用git filter-branch
操作方式。 當您運行git filter-branch
,Git的作用是:
根據您指定的任何gitrevisions樣式標准,枚舉您要過濾的分支中可到達的每個提交。 最后,僅--all
枚舉每個分支可到達的每個提交。
將提交列表放入“反向拓撲順序”,即從根提交(有史以來的第一個提交)開始,然后列出其直接子代,然后是其子代,依此類推。 因此,對於部分看起來像這樣的提交鏈:
G--H <-- branch1 / ...--E--F \\ I--J <-- branch2
該列表將以EF
結尾,然后是GHIJ
或IJGH
。
對於列表中的每個提交,執行以下步驟(或多或少):
$GIT_COMMIT
; -- whatever -filter
; $GIT_COMMIT
變成剛創建的新哈希ID”。 換句話說, git filter-branch
只復制每個提交。 如果新提交與它的父提交匹配,則使用--prune-empty
可以跳過“提交新提交”步驟。
在任何情況下,新提交的父提交都是映射的 ID。 也就是說,如果我們從原始提交A
開始,它是一個根提交並且沒有父母,我們將創建一個新的提交A'
:
A--B--C--... A' <-- (just made)
然后我們復制B
,因為那是A
的唯一孩子。 當我們通過git filter-branch
進行新的提交B'
我們使B'
的父對象為A'
而不是A
:
A--B--C--... A'-B' <-- (just made)
當我們從C
制作C'
時,我們將B'
作為其父代。 或者,如果-由於--prune-empty
規則,我們實際上並不做 B'
畢竟,我們將設置C'
的家長A'
這意味着您可以使用$GIT_COMMIT
來確定要保留的文件名。 您可以針對存儲庫中所有現有的提交對其進行測試,也可以構建自己的名稱映射以基於提交哈希或任何您喜歡的名稱進行保留。
請注意,通常,由於您要處理提交哈希的有向無環圖(DAG),因此通常要用於實現這些目的的測試是“祖先”。 如果提交A是提交B的祖先(更確切地說,如果A≼B ,那么您允許A = B) ,那么您將處於“之前”的情況。 這就是我在上面描述的內容:“在a123456
之前和包含”的a123456
使用較舊的名稱,而后續的提交使用較新的名稱。 git merge-base --is-ancestor AB
命令執行此A≼B測試,其結果作為shell命令退出狀態傳遞:
if git-merge-base --is-ancestor $GIT_COMMIT a123456; then ...; else ...; fi
測試是否$GIT_COMMIT
≼ a123456
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.