Câu hỏi Mở thư mục con (di chuyển) vào kho lưu trữ Git riêng biệt


tôi có một Git kho chứa một số thư mục con. Bây giờ tôi đã thấy rằng một trong các thư mục con không liên quan đến thư mục con khác và nên được tách ra thành một kho lưu trữ riêng biệt.

Làm thế nào tôi có thể làm điều này trong khi vẫn giữ lịch sử của các tập tin trong thư mục con?

Tôi đoán tôi có thể làm một bản sao và loại bỏ các phần không mong muốn của mỗi bản sao, nhưng tôi cho rằng điều này sẽ cung cấp cho tôi cây hoàn chỉnh khi kiểm tra một bản sửa đổi cũ hơn vv Điều này có thể chấp nhận được, nhưng tôi muốn có thể giả vờ rằng hai kho lưu trữ không có lịch sử được chia sẻ.

Chỉ cần làm rõ, tôi có cấu trúc sau:

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

Nhưng tôi muốn điều này thay vào đó:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/

1595
2017-12-11 13:57


gốc


Đây là tầm thường bây giờ với git filter-branch xem câu trả lời của tôi dưới đây. - jeremyjjbrown
@jeremyjjbrown là đúng. Điều này không còn khó thực hiện nữa nhưng rất khó để tìm ra câu trả lời đúng trên Google bởi vì tất cả các câu trả lời cũ đều thống trị kết quả. - Agnel Kurian


Các câu trả lời:


Cập nhật: Quá trình này rất phổ biến, nhóm git đã làm cho nó đơn giản hơn nhiều với một công cụ mới, git subtree. Xem ở đây: Mở thư mục con (di chuyển) vào kho lưu trữ Git riêng biệt


Bạn muốn sao chép kho lưu trữ của mình và sau đó sử dụng git filter-branch để đánh dấu mọi thứ nhưng thư mục con bạn muốn trong repo mới của bạn sẽ được thu thập rác.

  1. Để sao chép kho lưu trữ cục bộ của bạn:

    git clone /XYZ /ABC
    

    (Lưu ý: kho lưu trữ sẽ được nhân bản bằng cách sử dụng các liên kết cứng, nhưng đó không phải là vấn đề vì các tệp được liên kết cứng sẽ không bị sửa đổi - các tệp mới sẽ được tạo.)

  2. Bây giờ, chúng ta hãy bảo tồn các nhánh thú vị mà chúng ta muốn viết lại, và sau đó loại bỏ nguồn gốc để tránh đẩy nó vào và để đảm bảo rằng các commit cũ sẽ không được tham chiếu bởi nguồn gốc:

    cd /ABC
    for i in branch1 br2 br3; do git branch -t $i origin/$i; done
    git remote rm origin
    

    hoặc cho tất cả các nhánh từ xa:

    cd /ABC
    for i in $(git branch -r | sed "s/.*origin\///"); do git branch -t $i origin/$i; done
    git remote rm origin
    
  3. Bây giờ bạn có thể cũng muốn loại bỏ các thẻ không có quan hệ với tiểu dự án; bạn cũng có thể làm điều đó sau, nhưng bạn có thể cần phải tỉa bớt repo của bạn một lần nữa. Tôi đã không làm như vậy và có một WARNING: Ref 'refs/tags/v0.1' is unchanged cho tất cả các thẻ (vì tất cả chúng đều không liên quan đến tiểu dự án); Ngoài ra, sau khi xóa các thẻ như vậy sẽ có thêm không gian. Hiển nhiên git filter-branch nên có thể viết lại các thẻ khác, nhưng tôi không thể xác minh điều này. Nếu bạn muốn xóa tất cả các thẻ, hãy sử dụng git tag -l | xargs git tag -d.

  4. Sau đó sử dụng bộ lọc-chi nhánh và thiết lập lại để loại trừ các tập tin khác, vì vậy chúng có thể được cắt tỉa. Hãy cũng thêm --tag-name-filter cat --prune-empty để xóa các cam kết trống và viết lại các thẻ (lưu ý rằng điều này sẽ phải loại bỏ chữ ký của chúng):

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
    

    hoặc cách khác, để chỉ viết lại nhánh HEAD và bỏ qua các thẻ và các nhánh khác:

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
    
  5. Sau đó xóa các bản sao lưu dự phòng để không gian có thể được thực sự khai hoang (mặc dù bây giờ các hoạt động là phá hoại)

    git reset --hard
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
    git reflog expire --expire=now --all
    git gc --aggressive --prune=now
    

    và bây giờ bạn có một kho lưu trữ git cục bộ của thư mục con ABC với tất cả lịch sử được lưu giữ.

Lưu ý: Đối với hầu hết các mục đích sử dụng, git filter-branch thực sự nên có tham số được thêm vào -- --all. Vâng, đó là thực sự - -- -không gian- -- -  all. Điều này cần phải là tham số cuối cùng cho lệnh. Khi Matli phát hiện ra, điều này giữ cho các nhánh và thẻ dự án được bao gồm trong repo mới.

Chỉnh sửa: các đề xuất khác nhau từ các nhận xét bên dưới được kết hợp để đảm bảo, ví dụ, kho lưu trữ thực sự bị thu hẹp (không phải lúc nào cũng như vậy).


1155
2017-07-25 17:10



Câu trả lời rất hay. Cảm ơn! Và để thực sự có được chính xác những gì tôi muốn, tôi đã thêm "- --all" vào lệnh filter-branch. - matli
Tại sao bạn cần --no-hardlinks? Việc xóa một liên kết cứng sẽ không ảnh hưởng đến tệp khác. Các đối tượng Git cũng không thay đổi được. Chỉ khi bạn thay đổi quyền chủ sở hữu / tệp, bạn cần --no-hardlinks. - vdboor
Một bước bổ sung tôi muốn giới thiệu sẽ là "git remote rm origin". Điều này sẽ tiếp tục đẩy trở lại kho lưu trữ ban đầu, nếu tôi không nhầm. - Tom
Một lệnh khác để thêm vào filter-branch Là --prune-empty, để xóa các cam kết giờ trống. - Seth Johnson
Giống như Paul, tôi không muốn thẻ dự án trong repo mới của tôi, vì vậy tôi đã không sử dụng -- --all. Tôi cũng đã chạy git remote rm originvà git tag -l | xargs git tag -d trước git filter-branch chỉ huy. Điều này bị thu hẹp .git thư mục từ 60M đến ~ 300K. Lưu ý rằng tôi cần chạy cả hai lệnh này để giảm kích thước. - saltycrane


Easy Way ™

Nó chỉ ra rằng đây là một thực tế phổ biến và hữu ích mà các chúa git đã làm cho nó thực sự dễ dàng, nhưng bạn phải có một phiên bản mới hơn của git (> = 1.7.11 tháng 5 năm 2012). Xem ruột thừa để cài đặt git mới nhất. Ngoài ra, có một ví dụ thực tế bên trong hướng dẫn phía dưới.

  1. Chuẩn bị repo cũ

    pushd <big-repo>
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    Chú thích:  <name-of-folder> KHÔNG được chứa các ký tự đầu hoặc cuối. Ví dụ: thư mục có tên subproject PHẢI được chuyển thành subproject, KHÔNG PHẢI ./subproject/

    Lưu ý cho người dùng windows: khi độ sâu thư mục của bạn> 1, <name-of-folder> phải có dấu phân tách thư mục kiểu * nix (/). Ví dụ: thư mục có tên path1\path2\subproject PHẢI được chuyển thành path1/path2/subproject

  2. Tạo repo mới

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. Liên kết repo mới với Github hoặc bất cứ nơi nào

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. Dọn dẹp, nếu muốn

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    chú thích: Điều này để lại tất cả các tham chiếu lịch sử trong kho lưu trữ. Xem ruột thừa bên dưới nếu bạn thực sự lo ngại về việc đã cam kết mật khẩu hoặc bạn cần giảm kích thước tệp của mình .git thư mục.

...

Hướng dẫn

Đây là những các bước tương tự như trên, nhưng thực hiện theo các bước chính xác của tôi cho kho lưu trữ thay vì sử dụng <meta-named-things>.

Đây là một dự án tôi có để thực hiện các mô-đun trình duyệt JavaScript trong nút:

tree ~/Code/node-browser-compat

node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator

Tôi muốn tách ra một thư mục, btoa, vào một kho lưu trữ git riêng biệt

pushd ~/Code/node-browser-compat/
git subtree split -P btoa -b btoa-only
popd

Bây giờ tôi có một chi nhánh mới, btoa-only, chỉ có cam kết cho btoa và tôi muốn tạo một kho lưu trữ mới.

mkdir ~/Code/btoa/
pushd ~/Code/btoa/
git init
git pull ~/Code/node-browser-compat btoa-only

Tiếp theo tôi tạo một repo mới trên Github hoặc bitbucket, hoặc bất cứ điều gì và thêm nó là origin (btw, "origin" chỉ là một quy ước, không phải là một phần của lệnh - bạn có thể gọi nó là "remote-server" hoặc bất cứ thứ gì bạn thích)

git remote add origin git@github.com:node-browser-compat/btoa.git
git push origin -u master

Ngày hạnh phúc!

Chú thích: Nếu bạn tạo một repo với một README.md, .gitignore và LICENSE, bạn sẽ cần phải kéo đầu tiên:

git pull origin -u master
git push origin -u master

Cuối cùng, tôi sẽ muốn xóa thư mục khỏi repo lớn hơn

git rm -rf btoa

...

ruột thừa

Git mới nhất trên OS X

Để có phiên bản git mới nhất:

brew install git

Để pha chế cho OS X:

http://brew.sh

Git mới nhất trên Ubuntu

sudo apt-get update
sudo apt-get install git
git --version

Nếu điều đó không hoạt động (bạn có phiên bản cũ của ubuntu), hãy thử

sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git

Nếu vẫn không hiệu quả, hãy thử

sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree

Nhờ rui.araujo từ các bình luận.

xóa lịch sử của bạn

Theo mặc định, việc xóa các tệp khỏi git không thực sự xóa chúng khỏi git, nó chỉ cam kết rằng chúng không còn ở đó nữa. Nếu bạn thực sự muốn xóa các tham chiếu lịch sử (nghĩa là bạn đã có mật khẩu đã cam kết), bạn cần thực hiện việc này:

git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD

Sau đó, bạn có thể kiểm tra xem tệp hoặc thư mục của bạn không còn hiển thị trong lịch sử git nữa

git log -- <name-of-folder> # should show nothing

Tuy nhiên bạn không thể "đẩy" xóa thành github và những thứ tương tự. Nếu bạn cố gắng, bạn sẽ gặp lỗi và bạn sẽ phải git pull Trước khi bạn có thể git push - và sau đó bạn quay trở lại để có mọi thứ trong lịch sử của bạn.

Vì vậy, nếu bạn muốn xóa lịch sử từ "nguồn gốc" - nghĩa là xóa nó khỏi github, bitbucket, v.v. - bạn sẽ cần xóa repo và đẩy lại bản sao đã được cắt bớt của repo. Nhưng chờ đã - còn nữa! - Nếu bạn thực sự quan tâm đến việc loại bỏ mật khẩu hoặc một cái gì đó như thế bạn sẽ cần phải cắt bớt bản sao lưu (xem bên dưới).

chế tạo .git nhỏ hơn

Lệnh xóa lịch sử nói trên vẫn để lại một loạt các tập tin sao lưu - bởi vì git là tất cả các loại quá trong việc giúp bạn không làm hỏng repo của bạn một cách tình cờ. Nó cuối cùng sẽ xóa các tập tin mồ côi trong những ngày và tháng, nhưng nó để lại cho họ có một thời gian trong trường hợp bạn nhận ra rằng bạn vô tình xóa một cái gì đó bạn không muốn.

Vì vậy, nếu bạn thực sự muốn dọn sạch thùng rác đến giảm kích thước bản sao của một repo ngay lập tức bạn phải làm tất cả những thứ thực sự kỳ lạ này:

rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now

git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune

Điều đó nói rằng, tôi khuyên bạn không nên thực hiện các bước này trừ khi bạn biết rằng bạn cần - chỉ trong trường hợp bạn đã cắt tỉa thư mục con sai, bạn biết không? Các tệp sao lưu không được nhân bản khi bạn đẩy repo, chúng sẽ nằm trong bản sao cục bộ của bạn.

tín dụng


1124
2018-06-05 13:15



git subtree vẫn là một phần của thư mục 'đóng góp' và không được cài đặt theo mặc định trên tất cả các bản phân phối. github.com/git/git/blob/master/contrib/subtree - onionjake
@krlmlr sudo chmod + x /usr/share/doc/git/contrib/subtree/git-subtree.sh sudo ln -s /usr/share/doc/git/contrib/subtree/git-subtree.sh / usr / lib / git-core / git-subtree Để kích hoạt trên Ubuntu 13.04 - rui.araujo
Nếu bạn đã đẩy mật khẩu vào một kho lưu trữ công cộng, bạn nên thay đổi mật khẩu, không phải cố gắng loại bỏ nó khỏi repo công cộng và hy vọng không ai nhìn thấy nó. - Miles Rout
điều này dường như tạo ra một repo mới với nội dung của ABC/, nhưng repo mới không chứa thư mục ABC/ chính nó, như câu hỏi được hỏi. Bạn sẽ làm điều này như thế nào? - woojoo666
Giải pháp này không bảo tồn lịch sử. - Cœur


Câu trả lời của Paul tạo một kho lưu trữ mới chứa / ABC, nhưng không loại bỏ / ABC từ bên trong / XYZ. Lệnh sau sẽ xóa / ABC từ bên trong / XYZ:

git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD

Tất nhiên, kiểm tra nó trong kho chứa 'clone --no-hardlinks' trước, và theo nó với lệnh reset, gc và prune lệnh Paul.


131
2017-10-19 21:10



làm điều đó git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ABC" --prune-empty HEAD Và nó sẽ là nhiều nhanh hơn. bộ lọc chỉ mục hoạt động trên chỉ mục trong khi bộ lọc cây phải thanh toán và giai đoạn mọi thứ cho mọi cam kết. - fmarc
trong một số trường hợp rối tung lên lịch sử của kho XYZ là quá mức cần thiết ... chỉ đơn giản là "rm -rf ABC; git rm -r ABC; git commit -m'extracted ABC vào repo của riêng nó" sẽ hoạt động tốt hơn cho hầu hết mọi người. - Evgeny
Có thể bạn muốn sử dụng -f (force) trên lệnh này nếu bạn thực hiện nhiều lần, ví dụ: để xóa hai thư mục sau khi chúng được tách ra. Nếu không, bạn sẽ nhận được "Không thể tạo bản sao lưu mới". - Brian Carlton
Nếu bạn đang làm --index-filter phương pháp, bạn cũng có thể muốn làm điều đó git rm -q -r -f, để mỗi lời gọi sẽ không in một dòng cho mỗi tệp mà nó xóa. - Eric Naeseth
Tôi sẽ đề nghị chỉnh sửa câu trả lời của Phao-lô, chỉ vì Phao-lô thật kỹ lưỡng. - Erik Aronesty


Tôi đã phát hiện ra rằng để xóa lịch sử cũ khỏi kho lưu trữ mới, bạn phải thực hiện thêm một chút công việc sau filter-branch bậc thang.

  1. Làm bản sao và bộ lọc:

    git clone --no-hardlinks foo bar; cd bar
    git filter-branch --subdirectory-filter subdir/you/want
    
  2. Xóa mọi tham chiếu đến lịch sử cũ. “Origin” đã theo dõi bản sao của bạn, và “original” là nơi filter-branch lưu lại những thứ cũ:

    git remote rm origin
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    
  3. Ngay cả bây giờ, lịch sử của bạn có thể bị kẹt trong một gói dữ liệu mà fsck sẽ không chạm vào. Xé nó để cắt nhỏ, tạo một gói mới và xóa các đối tượng không sử dụng:

    git repack -ad
    

một lời giải thích về điều này bên trong hướng dẫn cho bộ lọc-chi nhánh.


94
2018-06-09 15:41



Tôi nghĩ đôi khi như git gc --aggressive --prune=now vẫn còn thiếu, phải không? - Albert
@Albert Lệnh repack đảm nhiệm điều đó và sẽ không có bất kỳ vật thể lỏng lẻo nào. - Josh Lee
chỉ repack đã không làm việc cho tôi, cần thiết để làm git gc - jsvnm
vâng, git gc --aggressive --prune=now giảm nhiều repo mới - Tomek Wyderka
Đơn giản và thanh lịch. Cảm ơn! - Marco Pelegrini


Chỉnh sửa: Bash script được thêm vào.

Các câu trả lời được đưa ra ở đây chỉ làm việc một phần cho tôi; Rất nhiều tệp lớn vẫn còn trong bộ nhớ cache. Những gì cuối cùng đã làm việc (sau giờ làm việc trong #git trên freenode):

git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT  --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

Với các giải pháp trước đó, kích thước kho lưu trữ là khoảng 100 MB. Cái này đã giảm xuống còn 1,7 MB. Có lẽ nó giúp ai đó :)


Tập lệnh bash sau tự động hóa tác vụ:

!/bin/bash

if (( $# < 3 ))
then
    echo "Usage:   $0 </path/to/repo/> <directory/to/extract/> <newName>"
    echo
    echo "Example: $0 /Projects/42.git first/answer/ firstAnswer"
    exit 1
fi


clone=/tmp/${3}Clone
newN=/tmp/${3}

git clone --no-hardlinks file://$1 ${clone}
cd ${clone}

git filter-branch --subdirectory-filter $2  --prune-empty --tag-name-filter cat -- --all

git clone file://${clone} ${newN}
cd ${newN}

git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

38
2017-08-20 14:11





Điều này không còn phức tạp đến mức bạn có thể sử dụng git filter-branch lệnh trên một bản sao của bạn repo để hủy bỏ các thư mục con bạn không muốn và sau đó đẩy đến điều khiển từ xa mới.

git filter-branch --prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git push <MY_NEW_REMOTE_URL> -f .

21
2018-03-22 20:55



Điều này làm việc như một say mê. YOUR_SUBDIR trong ví dụ trên là thư mục con mà bạn muốn GIỮ, mọi thứ khác sẽ bị xóa - J.T. Taylor
Cập nhật dựa trên nhận xét của bạn. - jeremyjjbrown
Điều này không trả lời câu hỏi. Từ tài liệu, nó nói The result will contain that directory (and only that) as its project root. và thực sự đây là những gì bạn sẽ nhận được, tức là cấu trúc dự án ban đầu không được bảo tồn. - NicBright
@NicBright Bạn có thể minh họa vấn đề của mình với XYZ và ABC như trong câu hỏi, để cho biết có vấn đề gì không? - Adam
@jeremyjjbrown là nó có thể tái sử dụng repo nhân bản và không sử dụng một repo mới, tức là câu hỏi của tôi ở đây stackoverflow.com/questions/49269602/… - Qiulang


Cập nhật: Mô đun git-subtree rất hữu ích khi nhóm git kéo nó vào lõi và làm cho nó git subtree. Xem ở đây: Mở thư mục con (di chuyển) vào kho lưu trữ Git riêng biệt

git-subtree có thể hữu ích cho việc này

http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt (không được chấp nhận)

http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/


19
2017-08-06 15:26



git-subtree bây giờ là một phần của Git, mặc dù nó nằm trong cây contrib, vì vậy không phải lúc nào cũng được cài đặt theo mặc định. Tôi biết nó được cài đặt bởi công thức Homebrew git, nhưng không có trang người đàn ông của nó. apenwarr do đó gọi phiên bản của mình đã lỗi thời. - echristopherson


Đây là một sửa đổi nhỏ đối với CoolAJ86'S Câu trả lời "Easy Way ™" để chia nhiều thư mục con (hãy cùng nói nào sub1sub2) vào một kho lưu trữ git mới.

Easy Way ™ (nhiều thư mục con)

  1. Chuẩn bị repo cũ

    pushd <big-repo>
    git filter-branch --tree-filter "mkdir <name-of-folder>; mv <sub1> <sub2> <name-of-folder>/" HEAD
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    Chú thích:  <name-of-folder> KHÔNG được chứa các ký tự đầu hoặc cuối. Ví dụ: thư mục có tên subproject PHẢI được chuyển thành subproject, KHÔNG PHẢI ./subproject/

    Lưu ý cho người dùng windows: khi độ sâu thư mục của bạn> 1, <name-of-folder> phải có dấu phân tách thư mục kiểu * nix (/). Ví dụ: thư mục có tên path1\path2\subproject PHẢI được chuyển thành path1/path2/subproject. Hơn nữa không sử dụng mvlệnh nhưng move.

    Lưu ý cuối cùng: sự khác biệt lớn và độc đáo với câu trả lời cơ sở là dòng thứ hai của tập lệnh "git filter-branch..."

  2. Tạo repo mới

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. Liên kết repo mới với Github hoặc bất cứ nơi nào

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. Dọn dẹp, nếu muốn

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    chú thích: Điều này để lại tất cả các tham chiếu lịch sử trong kho lưu trữ. Xem ruột thừa trong câu trả lời ban đầu nếu bạn thực sự lo ngại về việc đã cam kết mật khẩu hoặc bạn cần giảm kích thước tệp của mình .git thư mục.


13
2018-04-17 05:12



Điều này làm việc cho tôi với sửa đổi nhỏ. Bởi vì tôi sub1 và sub2 các thư mục không tồn tại với phiên bản ban đầu, tôi phải sửa đổi --tree-filter kịch bản như sau: "mkdir <name-of-folder>; if [ -d sub1 ]; then mv <sub1> <name-of-folder>/; fi". Cho lần thứ hai filter-branch lệnh Tôi đã thay thế <sub1> bằng <sub2>, bỏ qua việc tạo <name-of-folder> và bao gồm -f sau filter-branch để ghi đè cảnh báo của bản sao lưu hiện có. - pglezen
Điều này không hoạt động nếu bất kỳ subdir nào đã thay đổi trong lịch sử trong git. Làm thế nào điều này có thể được giải quyết? - nietras
@nietras xem câu trả lời của rogerdpack. Đã cho tôi một thời gian để tìm thấy nó sau khi đọc và hấp thụ tất cả các thông tin trong các câu trả lời khác. - Adam


Câu hỏi ban đầu muốn các tệp XYZ / ABC / (*) trở thành các tệp ABC / ABC / (*). Sau khi thực hiện câu trả lời được chấp nhận cho mã của riêng tôi, tôi nhận thấy rằng nó thực sự thay đổi tệp XYZ / ABC / (*) thành tệp ABC / (*). Trang bộ lọc chi nhánh thậm chí còn nói,

Kết quả sẽ chứa thư mục đó (và chỉ có đó) như là dự án gốc của nó. "

Nói cách khác, nó thúc đẩy thư mục cấp cao nhất "lên" một cấp. Đó là một sự khác biệt quan trọng bởi vì, ví dụ, trong lịch sử của tôi, tôi đã đổi tên thành một thư mục cấp cao nhất. Bằng cách quảng bá thư mục "lên" một cấp, git mất tính liên tục tại cam kết nơi tôi đã đổi tên.

I lost contiuity after filter-branch

Câu trả lời của tôi cho câu hỏi sau đó là tạo 2 bản sao của kho lưu trữ và xóa các thư mục bạn muốn giữ lại theo cách thủ công. Trang người đàn ông ủng hộ tôi với điều này:

[...] tránh sử dụng [lệnh này] nếu một cam kết đơn giản sẽ đủ để khắc phục sự cố của bạn


11
2017-07-25 10:01



Tôi thích phong cách của biểu đồ đó. Tôi có thể hỏi bạn đang sử dụng công cụ nào không? - Slipp D. Thompson
Tháp cho Mac. Tôi thực sự thích nó. Nó gần như có giá trị chuyển sang Mac cho chính nó. - MM.
Đúng vậy, mặc dù trong trường hợp của tôi, thư mục con của tôi targetdir đã từng đã đổi tên tại một số điểm và git filter-branch chỉ cần gọi nó là một ngày, xóa tất cả các cam kết được thực hiện trước khi đổi tên! Gây sốc, xem xét cách Git chuyên nghiệp theo dõi những thứ như vậy và thậm chí di chuyển các khối nội dung riêng lẻ! - Jay Allen
Oh, cũng vậy, nếu bất cứ ai tìm thấy chính mình trong cùng một thuyền, đây là lệnh tôi đã sử dụng. Đừng quên điều đó git rm mất nhiều arg, vì vậy không có lý do để chạy nó cho mỗi tập tin / thư mục: BYEBYE="dir/subdir2 dir2 file1 dir/file2"; git filter-branch -f --index-filter "git rm -q -r -f --cached --ignore-unmatch $BYEBYE" --prune-empty -- --all - Jay Allen