簡體   English   中英

包含所有重命名文件提交的篩選器分支

[英]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的作用是:

  1. 根據您指定的任何gitrevisions樣式標准,枚舉您要過濾的分支中可到達的每個提交。 最后,僅--all枚舉每個分支可到達的每個提交。

  2. 將提交列表放入“反向拓撲順序”,即從提交(有史以來的第一個提交)開始,然后列出其直接子代,然后是其子代,依此類推。 因此,對於部分看起來像這樣的提交鏈:

      G--H <-- branch1 / ...--E--F \\ I--J <-- branch2 

    該列表將以EF結尾,然后是GHIJIJGH

  3. 對於列表中的每個提交,執行以下步驟(或多或少):

    • 通過其哈希ID來檢查提交,該哈希ID臨時保存在變量$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_COMMITa123456

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM