簡體   English   中英

如何刪除Git存儲庫中不在工作目錄中的所有文件?

[英]How to remove all files in a Git repository that are not in the working directory?

我正在拆分最初位於單個Subversion存儲庫中的舊應用程序套件。

我已將其轉換為Git存儲庫並刪除了我不想要的內容,但我想通過刪除與已刪除文件關聯的歷史數據來縮小存儲庫(將保留原始存儲庫以供參考目的所以新的不需要它。

理想情況下,我想要做的是遍歷整個存儲庫並刪除工作目錄中不存在的任何文件或文件夾,以及與之關聯的任何歷史記錄。 這將留給我HEAD的內容和影響這些文件的提交歷史。 但是,我沒有遇到過這樣做的方法(孤兒HEAD沒有幫助,因為它沒有保留歷史記錄)。

這可能嗎? 我知道如何通過git-filter-branch從整個歷史記錄中刪除單個文件或文件夾,但是有太多的文件和文件夾,這是一個實用的方法......除非有一種方法可以過濾所有不在HEAD中的文件?

以下是如何使用git filter-branch來刪除所有不需要的文件:

  1. 在重命名的情況下,獲取您不希望在歷史記錄中顯示的舊名稱和新名稱的文件名列表。 例如,將它們放在名為toberemoved.txt的文件中

  2. 像這樣運行git filter-branch:

     $ git filter-branch --tree-filter "rm -f `cat toberemoved.txt`" branch1 branch2 ... 

這是git filter-branch的相關手冊頁:

   --tree-filter <command>
       This is the filter for rewriting the tree and its contents. The
       argument is evaluated in shell with the working directory set to
       the root of the checked out tree. The new tree is then used as-is
       (new files are auto-added, disappeared files are auto-removed -
       neither .gitignore files nor any other ignore rules HAVE ANY
       EFFECT!).

因此,只需確保要刪除的文件列表都相對於簽出樹的根目錄。

更新:

要獲取過去但不在當前工作目錄中的文件列表,可以運行以下命令。 請注意,您必須進一步努力保留重命名文件的“重命名前的歷史記錄”:

$ git log --raw |awk '/^:/ { if (! printed[$6]) { print $6; printed[$6] = 1 }}'|while read f;do if [ ! -f $f ]; then echo Deleted: $f;fi;done

$ 6是在-raw模式下顯示的提交中受影響的文件的名稱。

如果你想知道每次提交每個文件發生了什么([D] eleted,[R] enamed,[M] odified等),請參閱git log的--diff-filter選項。

也許其他人可以在重命名時查看如何查找跟蹤文件的先前名稱。

幫助第二個答案: “也許其他人可以在重命名時找到如何查找跟蹤文件的先前名稱。”

這將返回項目中的文件以及重命名它們的文件。

for file in `git ls-files`; do git log --follow --name-only --pretty=format: $file | sort -n -b | uniq | sed '/^\\s*$/d'; done

您可以使用它們從列表中排除。

整個解決方案是:

for file in `git ls-files`; do git log --follow --name-only --pretty=format: $file | sort -n -b | uniq | sed '/^\\s*$/d'; done > current.txt

git log --raw |awk '/^:/ { if (! printed[$6]) { print $6; printed[$6] = 1 }}'|while read f;do if [ ! -f $f ]; then echo $f;fi;done | sort > hist.txt

diff --new-line-format="" --unchanged-line-format="" hist.txt current.txt > for_remove.txt

我這樣做了幾次 - 提取單個文件的提交並從中創建新的存儲庫。 它有點像這樣:

$ c=10; for commit in $(git log --format=%h -- path/to/file|tac); do
      c=$((c+1))
      git format-patch -1 --stdout $commit > $c.patch
  done

這將創建補丁文件11.patch,12.patch等。 然后我編輯這些補丁(使用vim或perl看起來最適合這項工作),刪除我不感興趣的文件的整個數據庫,也可以修改名稱以及在diff hunk標頭中重命名的情況。

我會在新git存儲庫的補丁上使用git am。 如果某些事情沒有出現,那么我會核對新的git存儲庫並再次編輯補丁並重復git am。

我從10開始計算的原因是因為我懶得在補丁序列前面加一個前導0,而對於超過99的提交我只是從99開始。

暫無
暫無

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

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