programing

Git 하위 모듈을 분리하는 방법은 무엇입니까?

i4 2023. 5. 21. 10:57
반응형

Git 하위 모듈을 분리하는 방법은 무엇입니까?

Git 서브모듈을 서브모듈에서 분리하여 모든 코드를 코어 저장소로 가져오는 가장 좋은 방법은 무엇입니까?

하위 모듈 코드를 기본 저장소에 넣기만 하면 되는 경우 하위 모듈을 제거하고 파일을 주 저장소에 다시 추가하면 됩니다.

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"

하위 모듈의 기록도 보존하려는 경우 하위 모듈을 기본 저장소에 "병합"하여 하위 모듈 파일이 현재 기본 저장소에 있다는 점을 제외하고는 결과가 이전과 동일하도록 할 수 있습니다.

기본 모듈에서 다음을 수행해야 합니다.

# 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

결과 저장소가 약간 이상하게 보일 것입니다. 초기 커밋이 두 개 이상 있을 것입니다.하지만 그것은 Git에게 어떤 문제도 일으키지 않을 것입니다.

두 큰은 여전히 이두번솔큰장여실수것있다입니다는행할을 실행할 수 입니다.git blame또는git log원래 하위 모듈에 있던 파일에 있습니다.실제로 여기서 일어나는 일은 한 저장소 내의 많은 파일의 이름을 바꾸는 것일 뿐이며, Git는 이를 자동으로 감지해야 합니다. 여전히있는경우에 ,git log몇 옵션 몇가옵예션지)을 해 보십시오.--follow,-M,-C이름을 바꾸고 탐지를 복사하는 데 더 효과적입니다.

모든 파일 기록을 유지하면서 하위 모듈을 간단한 디렉토리로 변환하는 스크립트를 만들었습니다.그것은 고통받지 않습니다.git log --follow <file>다른 해결책들이 겪는 문제들.또한 모든 작업을 수행하는 매우 쉬운 한 줄 호출입니다.행운을 빌어요

Lucas Jenß의 블로그 게시물 "상위 저장소에 하위 모듈 통합"에서 설명한 우수한 작업을 기반으로 하지만 전체 프로세스를 자동화하고 몇 가지 다른 사례를 정리합니다.

최신 코드는 https://github.com/jeremysears/scripts/blob/master/bin/git-submodule-rewrite, 의 github에서 버그 수정으로 유지될 것이지만 적절한 스택 오버플로 응답 프로토콜을 위해 아래에 솔루션 전체를 포함했습니다.

용도:

$ git-submodule-rewrite <submodule-name>

git-transmodule-transmit:

#!/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

Git 1.8.5 이후(2013년 11월)(하위 모듈의 기록을 유지하지 않음):

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

다음과 같습니다.

  • 서브모듈의 등록을 취소하고 언로드합니다(, 내용 삭제).deinit 그므로러.mv 먼저),
  • 을 깨끗이 청소합니다..gitmodules당신을 위해 (rm),
  • 상위 레포의 색인에서 하위 모듈 SHA1을 나타내는 특수 항목을 제거합니다.rm).

되면 (R)deinit그리고.git rm으로 다시 할 수 .에서 폴더 이름을 원래 이름으로 다시 변경하고 Git repo에 일반 폴더로 추가할 수 있습니다.

Git에 , 된 "Git(< 1.8)"을 해야 할 수..git서브모듈 자체 내의 폴더, 사이먼 이스트가 언급한 대로


만약 당신이 서브모듈의 기록을 유지해야 한다면, jsears을 보세요. 그것은 다음과 같습니다.git filter-branch.

  1. git rm --cached the_submodule_path
  2. 을 에서모탈니에서 합니다..gitmodules파일 또는 유일한 하위 모듈인 경우 파일을 제거합니다.
  3. "commit submodule xyz"를 수행합니다.
  4. git add the_submodule_path
  5. 다른 커밋 "xyz의 추가 코드베이스"

저는 아직 더 쉬운 방법을 찾지 못했습니다.다음을 통해 3-5를 한 단계로 압축할 수 있습니다.git commit -a취미의 문제

여기에 많은 답이 있지만 모두 너무 복잡하여 원하는 것을 하지 못할 가능성이 높습니다.저는 대부분의 사람들이 그들의 역사를 유지하기를 원한다고 확신합니다.

는 이예서주레다같음습다니과는포요에입니다.git@site.com:main/main.git는 그고서듈레포는브모가 될 입니다.git@site.com:main/child.git이는 하위 모듈이 상위 repo의 루트 디렉터리에 있다고 가정합니다.필요에 따라 지침을 조정합니다.

상위 보고서를 복제하고 이전 하위 모듈을 제거하는 것으로 시작합니다.

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

이제 하위 저장소를 주 저장소에 업스트림에 추가하겠습니다.

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

다음 단계에서는 파일 경로를 변경하여 위치를 쉽게 변경할 수 있지만 merge-prep 분기의 파일을 위의 하위 모듈과 동일한 위치로 이동하려고 한다고 가정합니다.

mkdir child

.git 폴더를 제외한 모든 폴더와 파일을 하위 폴더로 이동합니다.

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

이제 파일을 마스터 분기로 다시 병합하기만 하면 됩니다.

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

실행하기 보이는지 합니다.git push

해야 할 입니다. git log는 이동된 파일을 않습니다.git log --follow filename파일의 전체 기록을 볼 수 있습니다.

우연히 두 개의 프로젝트에 대해 두 개의 저장소를 만들었는데, 두 개의 프로젝트를 분리하는 것이 의미가 없었습니다. 그래서 두 개의 프로젝트를 통합했습니다.

먼저 각 마스터 브랜치를 통합하는 방법을 보여준 다음 모든 브랜치로 확장할 수 있는 방법을 설명하겠습니다. 도움이 되길 바랍니다.

서브모듈이 작동하고 있고 디렉토리로 변환하려는 경우 다음 작업을 수행할 수 있습니다.

git clone project_uri project_name

여기서 우리는 깨끗한 복제를 수행합니다.이 프로세스에서는 하위 모듈을 초기화하거나 업데이트할 필요가 없으므로 생략합니다.

cd project_name
vim .gitmodules

편집.gitmodules원하는 편집기(또는 Vim)를 사용하여 교체하려는 하위 모듈을 제거합니다.제거해야 하는 선은 다음과 같습니다.

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

파일을 저장한 후,

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

여기서는 하위 모듈 관계를 완전히 제거하여 다른 보고서를 프로젝트에 추가할 수 있도록 합니다.

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

여기서 병합할 하위 모듈 리포지토리를 가져옵니다.

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

여기서 두 리포지토리의 병합 작업을 시작하지만 커밋하기 전에 중지합니다.

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

여기서 하위 모듈의 마스터 내용을 디렉터리 이름 앞에 붙이기 전의 디렉터리로 보냅니다.

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

여기서 병합의 변경 내용을 커밋하는 절차를 완료합니다.

이 작업을 완료한 후에는 다른 분기를 눌러 병합을 시작하고, 저장소에서 변경 사항을 수신할 분기를 체크아웃하고 병합 및 읽기 트리 작업을 수행할 분기를 변경하기만 하면 됩니다.

제가 찾은 가장 좋은 답은 다음과 같습니다.

http://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html

이 기사는 그 절차를 매우 잘 설명하고 있습니다.

@gyim의 답변을 조금 더 개선한 IMHO(IMHO)입니다.그는 주요 작업 복사본에서 여러 가지 위험한 변경 작업을 수행하고 있는데, 여기서 별도의 복제본을 운영한 다음 마지막에 함께 병합하는 것이 훨씬 더 쉽다고 생각합니다.

오류를 쉽게 정리하고 다시 시도할 수 있도록 별도의 디렉토리에서 top repo와 subrepo를 모두 확인합니다.

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

먼저 하위 보고서를 편집하여 모든 파일을 원하는 하위 디렉토리로 이동합니다.

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"

HEAD를 메모합니다.

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

이제 기본 보고서에서 하위 보고서를 제거합니다.

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"

그리고 마지막으로, 그것들을 병합합니다.

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

끝!아무 마법 없이 안전하게.

언제까지

git rm [-r] --cached submodule_path

돌아온다

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

컨텍스트:했다rm -r .git*서브모듈 폴더를 추가한 메인 프로젝트에서 서브모듈을 해제해야 한다는 것을 깨닫기 전에 서브모듈 폴더에 추가했습니다.일부를 디서브모듈링할 때 위와 같은 오류가 발생했지만 모두는 아닙니다.어쨌든, 나는 그것들을 실행함으로써 고쳤습니다, (물론, 그 후에,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"

이것은 역사를 보존하지 않습니다.

VonC의 답변을 바탕으로 이를 수행하는 간단한 bash 스크립트를 만들었습니다.add해야 합니다. 그렇지 했던 카드를 취소할 수 있습니다. 그렇지 않으면 이전을 실행 취소할 것입니다.rm서브모듈 자체를 위해.하위 모듈 디렉터리의 내용을 추가하는 것이 중요하며 디렉터리 자체의 이름을add지휘권

에.git-integrate-submodule:

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

메인 레포에서

  • gitrm --gitrm [compodules_repo]
  • git commit -m "하위 모듈이 제거되었습니다."
  • git push origin [마스터]

하위 모듈 repo

  • rm -rf.git

다시 메인 레포

  • git 추가 [compodules_repo]
  • git add
  • git commit -m "하위 모듈이 main에 추가되었습니다."
  • git push origin [마스터]

저는 (또한?)하는 것이 더 편리하다고 생각했습니다.서브모듈에서 로컬 커밋 데이터를 가져옵니다. 그렇지 않으면 데이터를 풀 수 있기 때문입니다. (리모트에 액세스할 수 없기 때문에 데이터를 푸시할 수 없습니다.)그래서 저는 submodule/.git를 remote_origin2로 추가하고 커밋을 가져와서 해당 분기에서 병합했습니다.아직 git에 익숙하지 않아서 submodule remote가 오리진으로 필요한지 잘 모르겠습니다.

이것이 제가 찾은 가장 단순한 것입니다.

하위 모듈 repo에서 HEAD에서 main repo로 병합하려는 경우:

  • git checkout -b "mergeMe"
  • mkdir "foo/bar/myLib/" repo에
  • git mv * "foo/bar/myLib/"으)로 이동합니다.
  • git commit -m "ready to merge into main"

하위 모듈을 제거하고 "foo/bar/myLib" 경로를 지운 후 main repo로 돌아갑니다.

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

다 된

보존된 역사

걱정마세요.


이는 일부 다른 답변과 거의 동일하다는 점에 유의하십시오.하지만 이것은 사용자가 서브모듈 레포를 소유하고 있다고 가정합니다.또한 서브모듈에 대한 향후 업스트림 변경사항을 쉽게 가져올 수 있습니다.

언급URL : https://stackoverflow.com/questions/1759587/how-to-un-submodule-a-git-submodule

반응형