un-subodule một mô hình con git


378

Làm thế nào để tôi hủy bỏ mô hình con git (đưa tất cả mã trở lại vào lõi)?

Như trong cách "nên" tôi, như trong "Thủ tục tốt nhất" ...


5
Lưu ý: với git1.8.3, bây giờ bạn có thể thử a git submodule deinit, xem câu trả lời của tôi bên dưới
VonC

6
Tôi có thể hiểu nhầm, nhưng git subodule deinit dường như loại bỏ mã.
Joe Germuska

2
Kể từ git 1.8.5 (tháng 11 năm 2013), một đơn giản git submodule deinit asubmodule ; git rm asubmodulelà đủ, như được minh họa trong câu trả lời của tôi dưới đây
VonC

xem xét sử dụng git cây con
Hib

Câu trả lời:


527

Nếu tất cả những gì bạn muốn là đưa mã mô đun con của bạn vào kho lưu trữ chính, bạn chỉ cần xóa mô hình con và thêm lại các tệp vào repo chính:

git rm --cached submodule_path # delete reference to submodule HEAD (no trailing slash)
git rm .gitmodules             # if you have more than one submodules,
                               # you need to edit this file instead of deleting!
rm -rf submodule_path/.git     # make sure you have backup!!
git add submodule_path         # will add files instead of commit reference
git commit -m "remove submodule"

Nếu bạn cũng muốn lưu giữ lịch sử của mô hình con, bạn có thể thực hiện một mẹo nhỏ: "hợp nhất" mô hình con vào kho lưu trữ chính để kết quả sẽ giống như trước đây, ngoại trừ các tệp mô hình con hiện đang ở trong kho chính.

Trong mô-đun chính, bạn sẽ cần phải làm như sau:

# Fetch the submodule commits into the main repository
git remote add submodule_origin git://url/to/submodule/origin
git fetch submodule_origin

# Start a fake merge (won't change any files, won't commit anything)
git merge -s ours --no-commit submodule_origin/master

# Do the same as in the first solution
git rm --cached submodule_path # delete reference to submodule HEAD
git rm .gitmodules             # if you have more than one submodules,
                               # you need to edit this file instead of deleting!
rm -rf submodule_path/.git     # make sure you have backup!!
git add submodule_path         # will add files instead of commit reference

# Commit and cleanup
git commit -m "removed submodule"
git remote rm submodule_origin

Kho lưu trữ kết quả sẽ trông hơi kỳ lạ: sẽ có nhiều hơn một cam kết ban đầu. Nhưng nó sẽ không gây ra vấn đề gì cho git.

Trong giải pháp thứ hai này, bạn sẽ có một lợi thế lớn là bạn vẫn có thể chạy git blame hoặc git log trên các tệp ban đầu trong các mô hình con. Trong thực tế, những gì bạn đã làm ở đây là đổi tên nhiều tệp trong một kho lưu trữ và git sẽ tự động phát hiện điều này. Nếu bạn vẫn gặp vấn đề với nhật ký git, hãy thử một số tùy chọn (--follow, -M, -C) để phát hiện đổi tên / sao chép tốt hơn.


3
Tôi nghĩ rằng tôi cần phải thực hiện phương pháp thứ hai của bạn (bảo tồn lịch sử) trên một số repos git tôi có. Bạn có thể giải thích phần nào của các lệnh trên làm cho các tệp từ mô hình con kết thúc trong thư mục con không? Có phải là bạn khi bạn thực hiện hợp nhất git mang lại tệp trong thư mục cấp cao nhất (với lịch sử của nó) nhưng khi bạn thực hiện git add subodule_path, nó có nghĩa là git mv cho mỗi tệp không?
Bowie Owens

5
Về cơ bản, có. Thủ thuật là git không lưu trữ các hoạt động đổi tên: thay vào đó, nó phát hiện ra chúng bằng cách nhìn vào các cam kết cha mẹ. Nếu có một nội dung tệp đã có trong cam kết trước đó, nhưng với một tên tệp khác, nó được coi là đổi tên (hoặc sao chép). Trong các bước trên, git mergeđảm bảo rằng sẽ có một "cam kết trước" cho mỗi tệp (tại một trong hai "bên" của hợp nhất).
gyim

6
Cảm ơn gyim, tôi đã bắt đầu một dự án mà tôi nghĩ sẽ hợp lý khi chia mọi thứ thành một vài kho lưu trữ và liên kết chúng lại với nhau bằng các mô hình con. Nhưng bây giờ có vẻ như đã qua thiết kế và tôi muốn kết hợp chúng lại với nhau mà không làm mất lịch sử của tôi.
Bowie Owens

4
@theduke Mình cũng gặp vấn đề này. Nó có thể được sửa bằng cách, trước khi làm theo các bước này, di chuyển tất cả các tệp từ kho lưu trữ mô đun con của bạn vào cấu trúc thư mục có cùng đường dẫn với kho lưu trữ mà bạn sắp hợp nhất vào: tức là. nếu mô hình con của bạn trong kho lưu trữ chính là trong foo /, trong mô hình con, hãy thực hiện mkdir foo && git mv !(foo) foo && git commit.
Chris Xuống

35
Cần thêm --allow-unrelated-historiesđể buộc hợp nhất tại hợp nhất giả như tôi đang nhận fatal: refusing to merge unrelated histories, thêm ở đây: github.com/git/git/blob/master/Documentation/RelNotes/iêu
vaskort

72

Kể từ git 1.8.5 (tháng 11 năm 2013 ) ( không lưu giữ lịch sử của mô hình con ):

mv yoursubmodule yoursubmodule_tmp
git submodule deinit yourSubmodule
git rm yourSubmodule
mv yoursubmodule_tmp yoursubmodule
git add yoursubmodule

Răng se:

  • hủy đăng ký và hủy tải (tức là xóa nội dung của ) mô hình con ( deinitdo đó, mv đầu tiên ),
  • dọn dẹp .gitmodulescho bạnrm ),
  • và loại bỏ mục đặc biệt đại diện cho mô hình con SHA1 đó trong chỉ mục của repo cha ( rm).

Khi việc xóa mô hình con hoàn thành ( deinitgit rm), bạn có thể đổi tên thư mục trở lại tên ban đầu và thêm nó vào git repo như một thư mục thông thường.

Lưu ý: nếu mô hình con được tạo bởi một Git cũ (<1.8), bạn có thể cần phải xóa .gitthư mục lồng trong chính mô hình con, như nhận xét của Simon East


Nếu bạn cần giữ lịch sử của mô hình con, hãy xem câu trả lời của jsears , sử dụng .git filter-branch


5
Điều này thực sự xóa nó khỏi cây làm việc trong 1.8.4 (toàn bộ thư mục con của tôi đã bị xóa).
Chris Xuống

@ChrisDown bạn có nghĩa là, deinitmột mình làm sạch cây làm việc từ mô hình con của bạn?
VonC

Vâng, nó loại bỏ tất cả nội dung trong thư mục mô hình con.
Chris Xuống

2
@mschuett không, bạn không thiếu thứ gì: một mô hình con không có .git trong đó ngay từ đầu. Nếu đó là trường hợp của bạn, thì đó là một repo lồng nhau, không phải là một mô hình con. Điều đó giải thích tại sao câu trả lời trên sẽ không áp dụng trong trường hợp của bạn. Để biết sự khác biệt giữa hai loại, xem stackoverflow.com/a/34410102/6309 .
VonC

1
@VonC Tôi hiện đang sử dụng 2.9.0.windows.1, tuy nhiên các mô hình con có thể đã được tạo ra vài năm trước trên một phiên bản git trước đó rất nhiều, tôi không chắc chắn. Tôi nghĩ rằng các bước dường như hoạt động miễn là tôi xóa tệp đó trước khi thực hiện add + commit cuối cùng.
Simon East

67

Tôi đã tạo một tập lệnh sẽ dịch một mô hình con sang một thư mục đơn giản, trong khi vẫn giữ lại tất cả lịch sử tập tin. Nó không bị các git log --follow <file>vấn đề mà các giải pháp khác phải chịu. Đây cũng là một cách gọi một dòng rất dễ thực hiện tất cả công việc cho bạn. G'luck.

Nó được xây dựng dựa trên công trình tuyệt vời của Lucas Jenß, được mô tả trong bài đăng trên blog của anh ấy " Tích hợp một mô hình con vào kho lưu trữ mẹ ", nhưng tự động hóa toàn bộ quá trình và dọn sạch một vài trường hợp góc khác.

Mã mới nhất sẽ được duy trì với các lỗi trên github tại https://github.com/jeremysears/scripts/blob/master/bin/git-submodule-rewrite , nhưng vì lợi ích của giao thức trả lời stackoverflow thích hợp, tôi đã đưa vào giải pháp trong toàn bộ dưới đây.

Sử dụng:

$ git-submodule-rewrite <submodule-name>

git-subodule-viết lại:

#!/usr/bin/env bash

# This script builds on the excellent work by Lucas Jenß, described in his blog
# post "Integrating a submodule into the parent repository", but automates the
# entire process and cleans up a few other corner cases.
# https://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html

function usage(){
  echo "Merge a submodule into a repo, retaining file history."
  echo "Usage: $0 <submodule-name>"
  echo ""
  echo "options:"
  echo "  -h, --help                Print this message"
  echo "  -v, --verbose             Display verbose output"
}

function abort {
    echo "$(tput setaf 1)$1$(tput sgr0)"
    exit 1
}

function request_confirmation {
    read -p "$(tput setaf 4)$1 (y/n) $(tput sgr0)"
    [ "$REPLY" == "y" ] || abort "Aborted!"
}

function warn() {
  cat << EOF
    This script will convert your "${sub}" git submodule into
    a simple subdirectory in the parent repository while retaining all
    contents and file history.

    The script will:
      * delete the ${sub} submodule configuration from .gitmodules and
        .git/config and commit it.
      * rewrite the entire history of the ${sub} submodule so that all
        paths are prefixed by ${path}.
        This ensures that git log will correctly follow the original file
        history.
      * merge the submodule into its parent repository and commit it.

    NOTE: This script might completely garble your repository, so PLEASE apply
    this only to a fresh clone of the repository where it does not matter if
    the repo is destroyed.  It would be wise to keep a backup clone of your
    repository, so that you can reconstitute it if need be.  You have been
    warned.  Use at your own risk.

EOF

  request_confirmation "Do you want to proceed?"
}

function git_version_lte() {
  OP_VERSION=$(printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' '\n' | head -n 4))
  GIT_VERSION=$(git version)
  GIT_VERSION=$(printf "%03d%03d%03d%03d" $(echo "${GIT_VERSION#git version}" | tr '.' '\n' | head -n 4))
  echo -e "${GIT_VERSION}\n${OP_VERSION}" | sort | head -n1
  [ ${OP_VERSION} -le ${GIT_VERSION} ]
}

function main() {

  warn

  if [ "${verbose}" == "true" ]; then
    set -x
  fi

  # Remove submodule and commit
  git config -f .gitmodules --remove-section "submodule.${sub}"
  if git config -f .git/config --get "submodule.${sub}.url"; then
    git config -f .git/config --remove-section "submodule.${sub}"
  fi
  rm -rf "${path}"
  git add -A .
  git commit -m "Remove submodule ${sub}"
  rm -rf ".git/modules/${sub}"

  # Rewrite submodule history
  local tmpdir="$(mktemp -d -t submodule-rewrite-XXXXXX)"
  git clone "${url}" "${tmpdir}"
  pushd "${tmpdir}"
  local tab="$(printf '\t')"
  local filter="git ls-files -s | sed \"s/${tab}/${tab}${path}\//\" | GIT_INDEX_FILE=\${GIT_INDEX_FILE}.new git update-index --index-info && mv \${GIT_INDEX_FILE}.new \${GIT_INDEX_FILE}"
  git filter-branch --index-filter "${filter}" HEAD
  popd

  # Merge in rewritten submodule history
  git remote add "${sub}" "${tmpdir}"
  git fetch "${sub}"

  if git_version_lte 2.8.4
  then
    # Previous to git 2.9.0 the parameter would yield an error
    ALLOW_UNRELATED_HISTORIES=""
  else
    # From git 2.9.0 this parameter is required
    ALLOW_UNRELATED_HISTORIES="--allow-unrelated-histories"
  fi

  git merge -s ours --no-commit ${ALLOW_UNRELATED_HISTORIES} "${sub}/master"
  rm -rf tmpdir

  # Add submodule content
  git clone "${url}" "${path}"
  rm -rf "${path}/.git"
  git add "${path}"
  git commit -m "Merge submodule contents for ${sub}"
  git config -f .git/config --remove-section "remote.${sub}"

  set +x
  echo "$(tput setaf 2)Submodule merge complete. Push changes after review.$(tput sgr0)"
}

set -euo pipefail

declare verbose=false
while [ $# -gt 0 ]; do
    case "$1" in
        (-h|--help)
            usage
            exit 0
            ;;
        (-v|--verbose)
            verbose=true
            ;;
        (*)
            break
            ;;
    esac
    shift
done

declare sub="${1:-}"

if [ -z "${sub}" ]; then
  >&2 echo "Error: No submodule specified"
  usage
  exit 1
fi

shift

if [ -n "${1:-}" ]; then
  >&2 echo "Error: Unknown option: ${1:-}"
  usage
  exit 1
fi

if ! [ -d ".git" ]; then
  >&2 echo "Error: No git repository found.  Must be run from the root of a git repository"
  usage
  exit 1
fi

declare path="$(git config -f .gitmodules --get "submodule.${sub}.path")"
declare url="$(git config -f .gitmodules --get "submodule.${sub}.url")"

if [ -z "${path}" ]; then
  >&2 echo "Error: Submodule not found: ${sub}"
  usage
  exit 1
fi

if ! [ -d "${path}" ]; then
  >&2 echo "Error: Submodule path not found: ${path}"
  usage
  exit 1
fi

main

Không hoạt động trên Ubuntu 16.04. Tôi đã gửi một yêu cầu kéo đến repo Github.
qznc

1
Bắt tốt, @qznc. Điều này đã được thử nghiệm trên OSX. Tôi sẽ vui vẻ hợp nhất điều đó khi nó đi qua cả hai nền tảng.
jsears

@qznc Ubuntu 16.04 hỗ trợ hợp nhất và trả lời cập nhật.
jsears

2
Đây là câu trả lời tốt nhất, giữ toàn bộ lịch sử. Rất đẹp!
CharlesB

1
Thực hiện tất cả công việc mà không có lỗi trong Git Bash 2.20.1.1 trên Windows 10 với phiên bản mới nhất từ ​​github: curl https://raw.githubusercontent.com/jeremysears/scripts/master/bin/git-submodule-rewrite > git-submodule-rewrite.sh./git-submodule-rewrite.sh <submodule-name>
Alexey

32
  1. git rm --cached the_submodule_path
  2. xóa phần mô hình con khỏi .gitmodulestệp hoặc nếu đó là mô hình con duy nhất, hãy xóa tệp.
  3. thực hiện một cam kết "loại bỏ mô hình con xyz"
  4. git add the_submodule_path
  5. một cam kết khác "đã thêm codebase của xyz"

Tôi chưa tìm thấy cách nào dễ dàng hơn. Bạn có thể nén 3-5 thành một bước thông qua git commit -a- vấn đề của hương vị.


6
Không nên .gitmodulesthay thế .submodules?
imz - Ivan Zakharyaschev

1
Nó phải là .gitmoduleskhông.submodules
mkey

1
Tôi đã phải xóa .gitthư mục của mô hình con trước khi git addhoạt động trên thư mục mô hình con
Carson Evans

16

Rất nhiều câu trả lời ở đây nhưng tất cả chúng dường như quá phức tạp và có khả năng không làm những gì bạn muốn. Tôi chắc chắn rằng hầu hết mọi người muốn giữ lịch sử của họ.

Trong ví dụ này, repo chính sẽ là git@site.com:main/main.gitvà repo mô đun con sẽ là git@site.com:main/child.git. Điều này giả định rằng mô hình con được đặt trong thư mục gốc của repo cha. Điều chỉnh các hướng dẫn khi cần thiết.

Bắt đầu bằng cách nhân bản repo cha và loại bỏ mô hình con cũ.

git clone git@site.com:main/main.git
git submodule deinit child
git rm child
git add --all
git commit -m "remove child submodule"

Bây giờ chúng tôi sẽ thêm repos con ngược dòng vào repo chính.

git remote add upstream git@site.com:main/child.git
git fetch upstream
git checkout -b merge-prep upstream/master

Bước tiếp theo giả định rằng bạn muốn di chuyển các tệp trên nhánh hợp nhất chuẩn bị vào cùng vị trí với mô hình con ở trên mặc dù bạn có thể dễ dàng thay đổi vị trí bằng cách thay đổi đường dẫn tệp.

mkdir child

di chuyển tất cả các thư mục và tệp ngoại trừ thư mục .git vào thư mục con.

git add --all
git commit -m "merge prep"

Bây giờ bạn có thể chỉ cần hợp nhất các tập tin của bạn trở lại vào nhánh chính.

git checkout master
git merge merge-prep # --allow-unrelated-histories merge-prep flag may be required 

Nhìn xung quanh và đảm bảo mọi thứ đều ổn trước khi chạy git push

Một điều bạn phải nhớ bây giờ là nhật ký git không theo mặc định theo dõi các tệp đã di chuyển, tuy nhiên bằng cách chạy, git log --follow filenamebạn có thể xem toàn bộ lịch sử các tệp của mình.


2
Tôi đã đi đến trận chung kết git merge merge-prepvà nhận được lỗi fatal: refusing to merge unrelated histories. Cách giải quyết là đây : git merge --allow-unrelated-histories merge-prep.
humblehacker

@humblehacker cảm ơn tôi đã thêm một ít bình luận trong trường hợp những người khác cũng chạy vào đây.
mschuett

1
Câu trả lời tốt nhất để giữ lịch sử của mô hình con. Cảm ơn bạn @mschuett
Anton Temchenko

Trong ví dụ ở đây, có cách nào để tìm nạp các tệp ngược dòng vào childthư mục, vì vậy bạn không phải di chuyển chúng sau này? Tôi có cùng tên tệp trong một mô hình con và repo chính ... vì vậy tôi chỉ nhận được một xung đột hợp nhất vì nó đang cố gắng hợp nhất hai tệp lại với nhau.
Skitterm

Có thể nhưng tôi không biết điều đó. Cá nhân tôi sẽ thực hiện một cam kết di chuyển các tệp trong repo mà bạn đang cố gắng di chuyển để chúng nằm trong thư mục bạn muốn trước khi kéo chúng vào.
mschuett

12

Điều đó xảy ra với chúng tôi rằng chúng tôi đã tạo ra 2 kho lưu trữ cho 2 dự án được ghép nối đến mức không có ý nghĩa gì để tách chúng ra, vì vậy chúng tôi đã hợp nhất chúng.

Tôi sẽ chỉ cho bạn cách hợp nhất các nhánh chính trong mỗi lần đầu tiên và sau đó tôi sẽ giải thích cách bạn có thể mở rộng điều này đến mọi nhánh bạn có, hy vọng nó sẽ giúp bạn.

Nếu bạn có mô hình con hoạt động và bạn muốn chuyển đổi nó thành một thư mục tại chỗ, bạn có thể làm:

git clone project_uri project_name

Ở đây chúng tôi làm một bản sao sạch để làm việc. Đối với quá trình này, bạn không cần phải khởi tạo hoặc cập nhật các mô hình con, vì vậy chỉ cần bỏ qua nó.

cd project_name
vim .gitmodules

Chỉnh sửa .gitmodulesvới trình chỉnh sửa yêu thích của bạn (hoặc Vim) để xóa mô hình con bạn dự định thay thế. Các dòng bạn cần loại bỏ sẽ trông giống như thế này:

[submodule "lib/asi-http-request"]
    path = lib/asi-http-request
    url = https://github.com/pokeb/asi-http-request.git

Sau khi lưu tệp,

git rm --cached directory_of_submodule
git commit -am "Removed submodule_name as submodule"
rm -rf directory_of_submodule

Ở đây chúng tôi loại bỏ hoàn toàn mối quan hệ mô hình con để chúng tôi có thể tạo mang lại repo khác cho dự án tại chỗ.

git remote add -f submodule_origin submodule_uri
git fetch submodel_origin/master

Ở đây chúng tôi lấy kho lưu trữ mô hình con để hợp nhất.

git merge -s ours --no-commit submodule_origin/master

Ở đây chúng tôi bắt đầu một hoạt động hợp nhất của 2 kho lưu trữ, nhưng dừng lại trước khi cam kết.

git read-tree --prefix=directory_of_submodule/ -u submodule_origin/master

Ở đây chúng tôi gửi nội dung của master trong mô hình con đến thư mục chứa nó trước khi đặt tiền tố tên thư mục

git commit -am "submodule_name is now part of main project"

Ở đây chúng tôi hoàn thành thủ tục thực hiện một cam kết về các thay đổi trong hợp nhất.

Sau khi hoàn thành việc này, bạn có thể đẩy và bắt đầu lại với bất kỳ nhánh nào khác để hợp nhất, chỉ cần kiểm tra nhánh trong kho lưu trữ của bạn sẽ nhận được các thay đổi và thay đổi nhánh bạn mang trong các hoạt động hợp nhất và cây đọc.


điều này dường như không lưu giữ lịch sử của các tệp mô hình con, tôi chỉ thấy một cam kết duy nhất trong nhật ký git cho các tệp được thêm vàodirectory_of_submodule
Anentropic

@Anentropic Xin lỗi vì sự chậm trễ trả lời. Tôi chỉ làm lại quy trình đầy đủ (với một sửa chữa nhỏ). Quy trình giữ toàn bộ lịch sử, nhưng nó có một điểm hợp nhất, có thể đó là lý do tại sao bạn không tìm thấy nó. Nếu bạn muốn xem lịch sử mô hình con chỉ cần thực hiện "nhật ký git", hãy tìm kiếm cam kết hợp nhất (trong ví dụ này là thông báo "Subodule_name hiện là một phần của dự án chính"). Nó sẽ có 2 xác nhận gốc (Hợp nhất: sdasda asdasd), git ghi lại cam kết thứ hai và bạn đã có tất cả lịch sử mô đun con / chủ của mình ở đó.
dvicino

Hiện tại bộ nhớ của tôi vẫn còn mơ hồ nhưng tôi nghĩ rằng tôi có thể lấy được lịch sử của các tệp mô đun con được hợp nhất bằng cách thực hiện git log original_path_of_file_in_submoduletức là đường dẫn được đăng ký trong git repo cho tệp (không còn tồn tại trên hệ thống tệp) mặc dù tệp mô hình con hiện đang sống tạisubmodule_path/new_path_of_file
Anentropic

Điều này không bảo tồn lịch sử rất tốt, và các đường dẫn đều sai. Tôi cảm thấy cần một cái gì đó như bộ lọc cây nhưng tôi không thể hiểu được ... đang thử những gì tôi đã tìm thấy ở đây: x3ro.de/2013/09/01/ chủ đề
Luke H

Câu trả lời này đã lỗi thời, stackoverflow.com/a/16162228/11343 (câu trả lời của VonC) cũng làm như vậy nhưng tốt hơn
CharlesB


6

Đây là phiên bản cải tiến một chút (IMHO) của câu trả lời của @ gyim. Anh ta đang thực hiện một loạt các thay đổi nguy hiểm trong bản sao làm việc chính, nơi tôi nghĩ việc vận hành trên các bản sao riêng biệt và sau đó hợp nhất chúng lại với nhau dễ dàng hơn nhiều.

Trong một thư mục riêng (để dễ dàng dọn dẹp và thử lại), hãy kiểm tra cả repo hàng đầu và subrepo.

git clone ../main_repo main.tmp
git clone ../main_repo/sub_repo sub.tmp

Đầu tiên chỉnh sửa subrepo để di chuyển tất cả các tệp vào thư mục con mong muốn

cd sub.tmp
mkdir sub_repo_path
git mv `ls | grep -v sub_repo_path` sub_repo_path/
git commit -m "Moved entire subrepo into sub_repo_path"

Ghi chú của TRỤ

SUBREPO_HEAD=`git reflog | awk '{ print $1; exit; }'`

Bây giờ xóa subrepo khỏi repo chính

cd ../main.tmp
rmdir sub_repo_path
vi .gitmodules  # remove config for submodule
git add -A
git commit -m "Removed submodule sub_repo_path in preparation for merge"

Và cuối cùng, chỉ cần hợp nhất chúng

git fetch ../sub.tmp
# remove --allow-unrelated-histories if using git older than 2.9.0
git merge --allow-unrelated-histories $SUBREPO_HEAD

Và thực hiện! An toàn và không có bất kỳ phép thuật.


... câu trả lời nào vậy? Có thể muốn tham khảo tên người dùng cũng như câu trả lời hàng đầu có thể thay đổi theo thời gian.
Contango

@Contango trả lời cập nhật. nhưng câu trả lời hàng đầu vẫn là câu trả lời hàng đầu bởi một người dẫn 400 điểm ;-)
dataless

Điều này có hoạt động không nếu subrepo đã chứa một thư mục có tên subrepotrong đó?
gièm pha

Ở bước cuối cùng tôi gặp lỗi sau: git merge $SUBREPO_HEAD fatal: refusing to merge unrelated historiesTôi có nên sử dụng git merge $SUBREPO_HEAD --allow-unrelated-historiestrong trường hợp này không? Hoặc nó nên làm việc mà không có và tôi đã phạm sai lầm?
Ti-m

1
@ Ti-m Vâng, đây chính xác là trường hợp hợp nhất hai lịch sử không chia sẻ bất kỳ cam kết nào. Sự bảo vệ chống lại lịch sử không liên quan dường như là mới trong git kể từ lần đầu tiên tôi viết bài này; Tôi sẽ cập nhật câu trả lời của tôi.
dataless

3

Để khi nào

git rm [-r] --cached submodule_path

trả lại

fatal: pathspec 'emr/normalizers/' did not match any files

Bối cảnh: Tôi đã thực hiện rm -r .git*trong các thư mục mô hình con của mình trước khi nhận ra rằng chúng cần được hủy đăng ký trong dự án chính mà tôi vừa thêm chúng. Tôi đã nhận được lỗi ở trên khi hủy đăng ký một số, nhưng không phải tất cả trong số họ. Dù sao, tôi đã sửa chúng bằng cách chạy, (dĩ nhiên là sau rm -r .git*)

mv submodule_path submodule_path.temp
git add -A .
git commit -m "De-submodulization phase 1/2"
mv submodule_path.temp submodule_path
git add -A .
git commit -m "De-submodulization phase 2/2"

Lưu ý rằng điều này không bảo tồn lịch sử.


3

Dựa trên câu trả lời của VonC , tôi đã tạo ra một tập lệnh bash đơn giản thực hiện điều này. Các addcuối cùng phải sử dụng ký tự đại diện nếu không nó sẽ khôi phục trở lại trước rmcho submodule riêng của mình. Điều quan trọng là thêm nội dung của thư mục mô đun con, và không đặt tên chính thư mục đó trong addlệnh.

Trong một tệp có tên git-integrate-submodule:

#!/usr/bin/env bash
mv "$1" "${1}_"
git submodule deinit "$1"
git rm "$1"
mv "${1}_" "$1"
git add "$1/**"

0

Tôi thấy thuận tiện hơn khi (cũng?) Lấy dữ liệu cam kết cục bộ từ mô hình con, bởi vì nếu không tôi sẽ mất chúng. (Không thể đẩy chúng khi tôi không truy cập vào điều khiển từ xa đó). Vì vậy, tôi đã thêm mô hình con / .git là remote_origin2, tìm nạp nó cam kết và hợp nhất từ ​​nhánh đó. Không chắc chắn nếu tôi vẫn cần mô hình con từ xa như nguồn gốc, vì tôi chưa đủ quen thuộc với git.


0

Đây là những gì tôi thấy tốt nhất và đơn giản nhất.

Trong repo mô đun con, từ CHÍNH bạn muốn hợp nhất thành repo chính:

  • git checkout -b "mergeMe"
  • mkdir "foo/bar/myLib/" (đường dẫn giống hệt như nơi bạn muốn các tệp trên repo chính)
  • git mv * "foo/bar/myLib/" (di chuyển tất cả vào con đường)
  • git commit -m "ready to merge into main"

Quay lại repo chính sau khi loại bỏ mô hình con và xóa đường dẫn "foo / bar / myLib":

  • git merge --allow-unrelated-histories SubmoduleOriginRemote/mergeMe

bùng nổ xong

lịch sử được bảo tồn

đừng lo lắng


Lưu ý điều này gần giống với một số câu trả lời khác. Nhưng điều này giả định rằng bạn sở hữu repo mô đun con. Ngoài ra, điều này giúp dễ dàng có được các thay đổi ngược dòng trong tương lai cho mô hình con.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.