2015-01-29 33 views
9

Làm cách nào để chuyển đổi một mô-đun con git (với một thư mục trong hệ thống tệp cục bộ thành từ xa) thành một git subtree, tốt nhất là giữ lại lịch sử cam kết của mô-đun con?Chuyển đổi môđun con Git thành subtree

Trả lời

8

Tập lệnh bash sau dựa trên bài đăng của Alexander Mikhailian (http://mikhailian.mova.org/node/233). Tôi đã sửa đổi nó một chút để gọi subtree add thay vì read-tree. Nó sẽ lấy danh sách các mô-đun con từ .gitmodule và trích xuất tiền tố, tên và url của mô-đun. Sau đó, nó loại bỏ từng mô-đun con và thêm chúng trở lại làm cây con ở cùng một vị trí. Nó cũng cho biết thêm điều khiển từ xa của mỗi submodule như một điều khiển từ xa để bạn có thể cập nhật các cây con bằng cách cung cấp tên của nó thay vì url của nó sau này (ví dụ: git subtree pull -P Foo Foo master --squash thay vì git subtree pull -P Foo https://example.com/foo.git master --squash)

Bạn có thể loại bỏ các lập luận --squash nếu bạn muốn nhập toàn bộ lịch sử của cây con vào kho lưu trữ của bạn. Với --squash, sẽ chỉ nhập phần đầu của cây con vào kho lưu trữ của bạn. Điều này có lẽ là những gì hầu hết mọi người muốn.

Để biết thêm thông tin, bạn có thể muốn đọc bài này bằng cách Atlassian: http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/

#!/bin/bash -x 
# extract the list of submodules from .gitmodule 
cat .gitmodules |while read i 
do 
if [[ $i == \[submodule* ]]; then 
    echo converting $i 

    # extract the module's prefix 
    mpath=$(echo $i | cut -d\" -f2) 

    # skip two lines 
    read i; read i; 

    # extract the url of the submodule 
    murl=$(echo $i|cut -d\= -f2|xargs) 

    # extract the module name 
    mname=$(basename $mpath) 

    # deinit the module 
    git submodule deinit $mpath 

    # remove the module from git 
    git rm -r --cached $mpath 

    # remove the module from the filesystem 
    rm -rf $mpath 

    # commit the change 
    git commit -m "Removed $mpath submodule" 

    # add the remote 
    git remote add -f $mname $murl 

    # add the subtree 
    git subtree add --prefix $mpath $mname master --squash 

    # fetch the files 
    git fetch $murl master 
fi 
done 
git rm .gitmodules 
+0

một ví dụ về cách thực hiện việc chuyển đổi này trên tất cả các chi nhánh có thể được tìm thấy ở đây; mã chuyển đổi được điều chỉnh một chút; cũng có một số mã bổ sung cho mục đích sao chép của tôi - bỏ qua nó hoặc cảm thấy tự do để sử dụng nó. https://github.com/eallik/curry-kics2-sync –

+1

Thay vì lặp lại tất cả các lệnh bạn có thể muốn xem xét sử dụng ví dụ: '' #!/bin/bash -x'' là shebang. –

+2

Trích xuất url của dòng submodule sẽ không hoạt động nếu không gian bị thiếu từ url submodule, sử dụng murl = $ (echo $ i | cut -d \ = -f2 | xargs) sẽ an toàn hơn – Wuvist

4

kịch bản Alexander Mikhailian của sửa đổi bởi @GaspardP không làm việc cho tôi.

Tôi đã sửa đổi và thực hiện cải tiến. Bây giờ, các subtrees mới sẽ trỏ đến cùng một cam kết như submodules cũ đã làm. Trước đây, tập lệnh sẽ chỉ tải xuống cam kết mới nhất từ ​​kho lưu trữ đích, có khả năng gây ra sự cố tương thích.

https://gist.github.com/Nikita240/0c98cea8f53a15e69699cd8bc40657c4

#!/bin/bash -x 
# This script will convert all your git submodules into git subtrees. 
# This script ensures that your new subtrees point to the same commits as the 
# old submodules did, unlike most other scripts that do this. 
# THIS SCRIPT MUST BE PLACED OUTSIDE OF YOUR REPOSITORY!!!!!!!!!! 
# Otherwise, the script will interfere with the git commits. 
# Save the script in your home directory as `~/subtrees.sh` 
# `cd` into your repository 
# Run `~/subtrees.sh` 
# Enjoy! 

# extract the list of submodules from .gitmodule 
cat .gitmodules |while read i 
do 
if [[ $i == \[submodule* ]]; then 
    echo converting $i 

    read i 

    # extract the module's prefix 
    mpath=$(echo $i | grep -E "(\S+)$" -o) 

    echo path: $mpath 

    read i 

    # extract the url of the submodule 
    murl=$(echo $i|cut -d\= -f2|xargs) 

    echo url: $murl 

    # extract the module name 
    mname=$(basename $mpath) 

    echo name: $mname 

    # extract the referenced commit 
    mcommit=$(git submodule status $mpath | grep -E "\S+" -o | head -1) 

    echo commit: $mcommit 

    # deinit the module 
    git submodule deinit $mpath 

    # remove the module from git 
    git rm -r --cached $mpath 

    # remove the module from the filesystem 
    rm -rf $mpath 

    # commit the change 
    git commit -m "Removed $mpath submodule at commit $mcommit" 

    # add the remote 
    git remote add -f $mname $murl 

    # add the subtree 
    git subtree add --prefix $mpath $mcommit --squash 

    # commit any left over uncommited changes 
    git commit -a -m "$mname cleaned up" 

    # fetch the files 
    git fetch $murl master 

    echo 
fi 
done 
git rm .gitmodules 
git commit -a -m "Removed .gitmodules" 
+2

+1. Tôi đã phải chỉnh sửa kịch bản này chỉ một chút; vì bất kỳ lý do gì, tên cam kết mà 'git submodule status' đã trả về có dấu gạch ngang hàng đầu (' -') trong đó. Tôi đã phải thêm một 'cut -d" - "-f2' vào cuối dòng đó để cắt nó ra. –

Các vấn đề liên quan