2010-08-05 28 views
5

Là tập hợp con của câu hỏi detach-subdirectory đã được thực hiện trước đó và xem xét thực tế là mặc dù đã có rất nhiều câu hỏi về quá trình tách và hợp nhất kho lưu trữ git, tôi không thể tìm thấy một trong đó chạm vào chủ đề tách khi submodules có mặt.Tách thư mục phụ với các mô-đun con thành một kho lưu trữ git riêng lẻ

Vì vậy, trong các tình huống sau:

.git/ 
.gitmodules 
folder/ 
    data/ 
    content/ 
     other_data/ 
     submoduleA/ 
     submoduleB/ 

Tôi muốn để có được hai kho với cơ cấu như sau:

.git/ 
data/ 

.git/ 
.gitmodules 
content/ 
    other_data/ 
    submoduleA/ 
    submoduleB/ 

Các trường hợp đầu tiên không phải là một vấn đề và có thể được giải quyết dễ dàng với phương pháp được mô tả trong detach-subdirectory.

Thứ hai không quá nhiều. Sự tồn tại của môđun con và thực tế là các phân tử .gitmodules chứa đường dẫn đầy đủ cho folder/content/submoduleAfolder/content/submoduleB làm cho một phần của lịch sử không nhất quán vì .gitmodules đề cập đến cấu trúc thư mục không tồn tại (khi bộ lọc nhánh được sử dụng).

Vì vậy, tôi muốn biết liệu có cách nào để thực hiện việc này mà không gây ra lịch sử không nhất quán hay không.

Trả lời

1

Tôi nghi ngờ (không được kiểm tra) rằng git filter-branch thứ hai sẽ có cơ hội sửa đổi nội dung .gitmodules cho mỗi cam kết của repo mới.

Nhưng thực tế là git submodule split command was in discussion early 2009.

sử dụng Đề xuất:

git submodule split [--url submodule_repo_url] submodule_dir \ 
    [alternate_dir...] 

Thay submodule_dir với một submodule mới được thành lập, giữ tất cả lịch sử của submodule_dir.
Lệnh này cũng ghi lại mỗi cam kết trong lịch sử của kho lưu trữ hiện tại để bao gồm sửa đổi chính xác sumodule_dir và các mục nhập .gitmodules thích hợp.

Tuy nhiên, tôi không thấy nó trong latest what's cooking.
Kịch bản trong bản vá được đề xuất có thể cung cấp cho bạn ý tưởng về loại cây viết lại cần thiết để cập nhật tệp .gitmodules.

+0

Sử dụng một lệnh git filter-branch thứ hai tôi đã có thể viết lại .gitmodules với một lệnh sed, tuy nhiên thực tế các thư mục submodule vẫn còn bị ảnh hưởng (cả với bộ lọc chỉ mục và bộ lọc cây). Chỉ bộ lọc thư mục con mới có thể thay đổi chúng nhưng sau đó .gitmodules bị xóa. Lệnh git submodule split dường như làm chính xác những gì tôi định, nhưng đọc thread tôi có ấn tượng rằng nó có một số vấn đề nên tôi không cảm thấy thoải mái khi sử dụng nó. – Unode

+0

@Unode: Tôi hiểu. Tôi không nghĩ rằng bản vá đặc biệt này đang được phát triển tích cực ngay bây giờ. – VonC

5

tôi đã có vấn đề chính xác giống như Unode và quản lý để giải quyết nó với các thủ tục sau:

git clone [email protected]:kdeldycke/kev-code.git 
cd kev-code 
git filter-branch --tree-filter "test -f ./.gitmodules && mv ./.gitmodules ./cool-cavemen/gitmodules || echo 'No .gitmodules file found'" -- --all 
git filter-branch --force --prune-empty --subdirectory-filter cool-cavemen --tag-name-filter cat -- --all init..HEAD 
git filter-branch --force --tree-filter "test -f ./gitmodules && mv ./gitmodules ./.gitmodules || echo 'No gitmodules file found'" -- --all 
git filter-branch --force --tree-filter "test -f ./.gitmodules && sed -i 's/cool-cavemen\///g' ./.gitmodules || echo 'No .gitmodules file found'" -- --all 
git remote rm origin 
rm -rf .git/refs/original/ 
git reflog expire --all 
git gc --aggressive --prune 
git remote add origin [email protected]:kdeldycke/cool-cavemen.git 
git push -u origin master --force --tags 

Như bạn thấy, các trick là để tạm thời đổi tên các tập tin .gitmodules và sử dụng sed để viết lại nội dung của nó. Bạn có thể nhận tất cả các chi tiết và số context of this procedure on my blog.

+0

Bạn có thể muốn bao gồm tùy chọn '--tag-name-filter cat' trong tất cả các lệnh lọc-chi nhánh để bảo toàn thẻ sau khi lọc. – kolyuchiy

+0

Cảm ơn bạn đã ghi lại điều này. Hai điều tôi phải tinh chỉnh để làm việc này. Đầu tiên, tôi nghĩ bạn giả sử một commit ban đầu được gắn thẻ là 'init' cho phạm vi' init..HEAD'. Thứ hai, tôi phải thêm '-e' vào lệnh sed, ví dụ:' sed -i -e 's/cool-cavemen \ /// g' ./. Gitmodules' – Von

0

Để xây dựng câu trả lời của Kevin: giả định rằng không có mô-đun con nào tồn tại bên ngoài cool/cavemen - thư mục bị tách rời (nếu không chỉnh sửa phức tạp hơn.gitmodules sẽ là cần thiết để loại bỏ những phần thêm), điều này có thể đạt được nhiều nhanh hơn và trong một bước sử dụng một index-filter:

$ git filter-branch --subdirectory-filter cool/cavemen --index-filter $' 
hash=$(git rev-parse --verify $GIT_COMMIT:.gitmodules 2>/dev/null) && 
git update-index --add --cacheinfo 100644 $(git cat-file -p $hash | 
sed \'s/cool\\/cavemen\\///g\' | git hash-object -w --stdin) .gitmodules || 
true' --tag-name-filter cat --prune-empty -- --all 

Là một lợi ích bổ sung, nếu cool/cavemen không tồn tại trong mỗi sửa đổi hoặc chi nhánh chỉ những sửa đổi hoặc chi nhánh đã chứa cool/cavemen sẽ được xem xét.

Nếu đây là trường hợp bạn có thể muốn chạy sau để loại bỏ tài liệu tham khảo không thay đổi:

$ git for-each-ref --format='%(refname)' | 
grep -vF "$(git for-each-ref --format='%(refname)' refs/original | 
sed 's/refs\/original\///g')" | xargs -n 1 git update-ref -d 
Các vấn đề liên quan