자식 서브 모듈을 서브 모듈 해제하려면 어떻게해야합니까 (모든 코드를 코어로 다시 가져 오는 중)?
"최상의 절차"에서와 같이 "어떻게해야"하는지와 같이 ...
자식 서브 모듈을 서브 모듈 해제하려면 어떻게해야합니까 (모든 코드를 코어로 다시 가져 오는 중)?
"최상의 절차"에서와 같이 "어떻게해야"하는지와 같이 ...
답변:
서브 모듈 코드를 메인 리포지토리에 넣는 것만으로 서브 모듈을 제거하고 파일을 메인 리포지토리에 다시 추가하면됩니다.
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 merge
에서 모든 파일에 대해 "이전 커밋"이 있는지 확인합니다 (병합의 "양쪽"중 하나에서).
mkdir foo && git mv !(foo) foo && git commit
.
--allow-unrelated-histories
나는 점점되었을 때 가짜 병합에서 병합을 강제로 fatal: refusing to merge unrelated histories
: 자세한 내용은 여기, github.com/git/git/blob/master/Documentation/RelNotes/...을
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
)rm
.하위 모듈 제거가 완료되면 ( deinit
및 git rm
) 폴더 이름을 원래 이름으로 바꾸고 git repo에 일반 폴더로 추가 할 수 있습니다.
참고 : 하위 모듈이 이전 Git (<1.8)에 의해 작성된 경우 Simon East의 설명 에 .git
따라 하위 모듈 자체 내에서 중첩 된 폴더 를 제거해야합니다.
당신이 서브 모듈의 역사를 유지해야하는 경우, 참조 jsears 의 대답 하는 용도, git filter-branch
.
deinit
혼자서 하위 모듈에서 작업 트리를 청소 했습니까?
모든 파일 히스토리를 유지하면서 하위 모듈을 간단한 디렉토리로 변환하는 스크립트를 작성했습니다. git log --follow <file>
다른 솔루션이 겪는 문제로 고통받지 않습니다 . 또한 모든 작업을 수행하는 매우 쉬운 한 줄 호출입니다. 행운을 빈다.
그의 블로그 포스트 " 부모 저장소에 서브 모듈 통합 "에 설명 된 Lucas Jenß의 훌륭한 작업을 기반으로 하지만 전체 프로세스를 자동화하고 다른 몇 가지 경우를 정리합니다.
최신 코드는 https://github.com/jeremysears/scripts/blob/master/bin/git-submodule-rewrite의 github에서 버그 수정으로 유지 되지만 적절한 스택 오버 플로우 응답 프로토콜을 위해 아래에 전체적으로 솔루션이 있습니다.
용법:
$ git-submodule-rewrite <submodule-name>
자식 서브 모듈 다시 쓰기 :
#!/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
curl https://raw.githubusercontent.com/jeremysears/scripts/master/bin/git-submodule-rewrite > git-submodule-rewrite.sh
하고./git-submodule-rewrite.sh <submodule-name>
git rm --cached the_submodule_path
.gitmodules
파일 에서 하위 모듈 섹션을 제거 하거나 유일한 하위 모듈 인 경우 파일을 제거하십시오.git add the_submodule_path
아직 더 쉬운 방법을 찾지 못했습니다. git commit -a
맛의 문제를 통해 3-5 단계를 한 단계로 압축 할 수 있습니다 .
.gitmodules
대신 해서는 안 .submodules
됩니까?
.gitmodules
하지.submodules
.git
하기 전에 서브 모듈의 디렉토리를 git add
서브 모듈 폴더에 작동합니다
여기에 많은 답변이 있지만 모두 복잡해 보이며 원하는 것을하지 않을 수 있습니다. 나는 대부분의 사람들이 그들의 역사를 지키기를 원한다고 확신합니다.
이 예에서 기본 리포지토리는 git@site.com:main/main.git
이고 하위 모듈 리포지토리는입니다 git@site.com:main/child.git
. 이것은 서브 모듈이 상위 저장소의 루트 디렉토리에 있다고 가정합니다. 필요에 따라 지시 사항을 조정하십시오.
부모 저장소를 복제하고 이전 하위 모듈을 제거하여 시작하십시오.
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
다음 단계에서는 파일 경로를 변경하여 위치를 쉽게 변경할 수 있지만 병합 준비 분기의 파일을 하위 모듈과 동일한 위치로 이동한다고 가정합니다.
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 merge merge-prep
오류를 받았다 fatal: refusing to merge unrelated histories
. 해결 방법은 다음과 같습니다 git merge --allow-unrelated-histories merge-prep
..
child
디렉토리 로 가져올 수있는 방법이 있습니까? 따라서 나중에 이동할 필요가 없습니까? 하위 모듈과 기본 저장소에 동일한 파일 이름이 있습니다 ... 따라서 두 파일을 병합하려고하기 때문에 병합 충돌이 발생합니다.
우리는 두 개의 프로젝트를 위해 두 개의 저장소를 만들어 서로 분리되어 의미가 없었으므로 병합했습니다.
먼저 각 마스터 브랜치를 병합하는 방법을 보여 드리고이를 모든 브랜치로 확장하는 방법을 설명하겠습니다. 도움이 되길 바랍니다.
서브 모듈이 작동하고 있고이를 서브 디렉토리로 변환하려면 다음을 수행하십시오.
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
여기서 우리는 서브 모듈에있는 master의 내용을 디렉토리 이름 앞에 붙인 디렉토리로 보낸다.
git commit -am "submodule_name is now part of main project"
이제 병합 변경 사항을 커밋하는 절차를 완료했습니다.
이 작업을 마친 후에는 다른 분기에서 병합을 다시 시작하고 병합 할 수 있습니다. 변경 사항을 수신 할 저장소의 분기를 체크 아웃하고 병합 및 읽기 트리 작업을 수행하는 분기를 변경하기 만하면됩니다.
directory_of_submodule
git log original_path_of_file_in_submodule
인데 파일에 대한 git repo에 등록 된 경로 (파일 시스템에 더 이상 존재하지 않음) 를 수행하여 병합 된 하위 모듈 파일의 기록을 얻을 수 있다고 생각 합니다.submodule_path/new_path_of_file
내가 찾은 이것에 대한 가장 좋은 대답은 다음과 같습니다.
http://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html
이 기사는 절차를 잘 설명합니다.
@gyim의 답변이 약간 개선 된 버전 (IMHO)이 있습니다. 그는 주 작업 복사본에서 여러 가지 위험한 변화를 겪고 있습니다. 여기서 별도의 클론에서 작동하고 끝에서 병합하는 것이 훨씬 쉽다고 생각합니다.
실수를 쉽게 정리하고 다시 시도하기 위해 별도의 디렉토리에서 최상위 저장소와 하위 저장소를 모두 확인하십시오.
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
그리고 끝났다! 안전하고 마술없이.
subrepo
?
git merge $SUBREPO_HEAD fatal: refusing to merge unrelated histories
사용해야 git merge $SUBREPO_HEAD --allow-unrelated-histories
합니까? 아니면 작동하지 않고 실수해야합니까?
언제
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"
이것은 기록을 유지하지 않습니다.
여기 내가 가장 잘 찾은 것이 가장 간단합니다.
하위 모듈 저장소의 HEAD에서 기본 저장소로 병합하려고합니다.
git checkout -b "mergeMe"
mkdir "foo/bar/myLib/"
(주 리포지토리에서 파일을 원하는 위치와 동일한 경로)git mv * "foo/bar/myLib/"
(경로로 모두 이동)git commit -m "ready to merge into main"
서브 모듈을 제거하고 "foo / bar / myLib"경로를 삭제 한 후 메인 저장소로 돌아갑니다.
git merge --allow-unrelated-histories SubmoduleOriginRemote/mergeMe
붐 완료
역사 보존
걱정 마
이것은 다른 답변과 거의 동일합니다. 그러나 이것은 하위 모듈 저장소를 소유하고 있다고 가정합니다. 또한 하위 모듈에 대한 향후 업스트림 변경을 쉽게 얻을 수 있습니다.
git submodule deinit
, 아래 내 대답을