기존 Git 저장소를 다른 저장소로 가져 오는 방법은 무엇입니까?
XXX 라는 폴더에 Git 저장소가 있고 YYY 라는 두 번째 Git 저장소가 있습니다.
XXX 리포지토리를 YZZ 리포지토리로 ZZZ 라는 하위 디렉터리 로 가져오고 모든 XXX 의 변경 기록을 YYY에 추가 하려고 합니다.
이전 폴더 구조 :
XXX
|- .git
|- (project files)
YYY
|- .git
|- (project files)
다음의 폴더 구조 :
YYY
|- .git <-- This now contains the change history from XXX
|- ZZZ <-- This was originally XXX
|- (project files)
|- (project files)
이 작업을 수행 할 수 있습니까, 아니면 하위 모듈을 사용해야합니까?
아마도 가장 간단한 방법은 XXX 항목 을 YYY 의 지점으로 가져온 다음 마스터로 병합하는 것입니다.
에 YYY :
git remote add other /path/to/XXX
git fetch other
git checkout -b ZZZ other/master
mkdir ZZZ
git mv stuff ZZZ/stuff # repeat as necessary for each file/dir
git commit -m "Moved stuff to ZZZ"
git checkout master
git merge ZZZ --allow-unrelated-histories # should add ZZZ/ to master
git commit
git remote rm other
git branch -d ZZZ # to get rid of the extra branch before pushing
git push # if you have a remote, that is
나는 실제로 몇 가지 내 repos로 이것을 시도했으며 작동합니다. Jörg의 답변 과 달리 다른 저장소를 계속 사용할 수는 없지만 어쨌든 지정하지 않았다고 생각합니다.
참고 : 이것은 2009 년에 처음 작성되었으므로 git은 아래 답변에 언급 된 하위 트리 병합을 추가했습니다. 물론이 방법은 여전히 효과가 있지만 아마도 그 방법을 오늘 사용할 것입니다.
두 번째 저장소의 정확한 커밋 히스토리를 유지하고 향후 업스트림 변경 사항을 쉽게 병합 할 수있는 기능을 유지하려는 경우 원하는 방법이 있습니다. 병합 된 저장소를 서브 디렉토리로 이동하기 위해 서브 트리의 수정되지 않은 히스토리가 리포지토리로 반입되고 하나의 병합 커밋이 발생합니다.
git remote add XXX_remote <path-or-url-to-XXX-repo>
git fetch XXX_remote
git merge -s ours --no-commit --allow-unrelated-histories XXX_remote/master
git read-tree --prefix=ZZZ/ -u XXX_remote/master
git commit -m "Imported XXX as a subtree."
다음과 같이 업스트림 변경 사항을 추적 할 수 있습니다.
git pull -s subtree XXX_remote master
Git은 병합을 수행하기 전에 루트가있는 위치를 자체적으로 파악하므로 후속 병합에 접두사를 지정할 필요가 없습니다.
2.9 이전의 힘내 버전 :에 --allow-unrelated-histories
옵션을 전달할 필요가 없습니다 git merge
.
단계 를 사용 read-tree
하고 건너 뛰는 다른 대답의 방법은 merge -s ours
cp로 파일을 복사하고 결과를 커밋하는 것과 사실상 다르지 않습니다.
원본 소스는 github의 "Subtree Merge"도움말에서 제공 됩니다.
git-subtree
는 히스토리를 유지하면서 (그리고이 질문과 관련이없는 것처럼 하위 트리의 히스토리를 분할하면서) 여러 리포지토리를 하나로 병합하는이 유스 케이스를 위해 설계된 스크립트입니다. 릴리스 1.7.11 이후 git 트리의 일부로 배포됩니다 .
<repo>
개정시 저장소 를 <rev>
서브 디렉토리로 병합하려면 다음과 같이 <prefix>
사용하십시오 git subtree add
.
git subtree add -P <prefix> <repo> <rev>
git-subtree 는보다 사용자 친화적 인 방식으로 하위 트리 병합 전략 을 구현합니다 .
귀하의 경우 YYY 저장소 내에서 다음을 실행합니다.
git subtree add -P ZZZ /path/to/XXX.git master
집합 "로 힘내 커뮤니티에 알려져있다 Git 저장소 자체에서이의 잘 알려진 예입니다 어느 멋진 병합 이 설명 리누스 토발즈 (Linus Torvalds)가 망할 놈의 메일 링리스트에 전자 메일에 사용되는 제목 후에는"( 병합). 이 경우 gitk
Git GUI의 일부인 Git GUI는 실제로 별도의 프로젝트였습니다. Linus는 해당 리포지토리를 Git 리포지토리에 병합하여
- 항상 Git의 일부로 개발 된 것처럼 Git 저장소에 나타납니다.
- 모든 역사는 그대로 유지되고
- 기존 저장소에서 독립적으로 개발할 수 있으며 변경 사항은 간단하게 변경
git pull
됩니다.
전자 메일에는 재생산에 필요한 단계가 포함되어 있지만 마음이 희미하지는 않습니다. 첫째, Linus 는 Git을 작성 했으므로 아마도 Git에 대해 조금 더 알고있을 것입니다. 두번째는 거의 5 년 전입니다. Git은 그 이후로 상당히 향상 되었으므로 훨씬 쉬울 것입니다.
특히 요즘에는 특정 상황에서 gitk 서브 모듈을 사용한다고 생각합니다.
이를 수행하는 간단한 방법은 git format-patch를 사용하는 것입니다.
우리가 2 개의 git 저장소 foo 및 bar 가 있다고 가정하십시오 .
foo 는 다음을 포함합니다 :
- foo.txt
- .git
바 내용 :
- bar.txt
- .git
그리고 우리 는 바 히스토리 와이 파일들을 포함하는 foo 로 끝나고 싶습니다 :
- foo.txt
- .git
- foobar / bar.txt
그렇게하려면 :
1. create a temporary directory eg PATH_YOU_WANT/patch-bar
2. go in bar directory
3. git format-patch --root HEAD --no-stat -o PATH_YOU_WANT/patch-bar --src-prefix=a/foobar/ --dst-prefix=b/foobar/
4. go in foo directory
5. git am PATH_YOU_WANT/patch-bar/*
그리고 우리가 bar에서 모든 메시지 커밋을 다시 작성하려면 예를 들어 Linux에서 할 수 있습니다.
git filter-branch --msg-filter 'sed "1s/^/\[bar\] /"' COMMIT_SHA1_OF_THE_PARENT_OF_THE_FIRST_BAR_COMMIT..HEAD
각 커밋 메시지의 시작 부분에 "[bar]"가 추가됩니다.
이 기사를 기반 으로 하위 트리를 사용하는 것이 나에게 효과적이며 적용 가능한 기록 만 전송되었습니다. 단계가 필요한 경우 여기에 게시하십시오 (자리 표시자를 해당하는 값으로 바꾸십시오).
소스 리포지토리에서 하위 폴더를 새 분기로 분할
git subtree split --prefix=<source-path-to-merge> -b subtree-split-result
분할 결과 분기의 대상 리포지토리 병합
git remote add merge-source-repo <path-to-your-source-repository>
git fetch merge-source-repo
git merge -s ours --no-commit merge-source-repo/subtree-split-result
git read-tree --prefix=<destination-path-to-merge-into> -u merge-source-repo/subtree-split-result
변경 사항을 확인하고 커밋
git status
git commit
잊지 마세요
subtree-split-result
분기 를 삭제하여 정리
git branch -D subtree-split-result
소스 저장소에서 데이터를 가져 오기 위해 추가 한 리모컨을 제거하십시오.
git remote rm merge-source-repo
이 함수는 원격 저장소를 로컬 저장소 디렉토리로 복제하고, 모든 커밋을 병합 한 후 git log
원래 커밋과 적절한 경로를 보여줍니다.
function git-add-repo
{
repo="$1"
dir="$(echo "$2" | sed 's/\/$//')"
path="$(pwd)"
tmp="$(mktemp -d)"
remote="$(echo "$tmp" | sed 's/\///g'| sed 's/\./_/g')"
git clone "$repo" "$tmp"
cd "$tmp"
git filter-branch --index-filter '
git ls-files -s |
sed "s,\t,&'"$dir"'/," |
GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
' HEAD
cd "$path"
git remote add -f "$remote" "file://$tmp/.git"
git pull "$remote/master"
git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
git remote remove "$remote"
rm -rf "$tmp"
}
사용하는 방법:
cd current/package
git-add-repo https://github.com/example/example dir/to/save
약간 변경하면 병합 된 저장소의 파일 / 디렉토리를 다른 경로로 이동할 수도 있습니다. 예를 들면 다음과 같습니다.
repo="https://github.com/example/example"
path="$(pwd)"
tmp="$(mktemp -d)"
remote="$(echo "$tmp" | sed 's/\///g' | sed 's/\./_/g')"
git clone "$repo" "$tmp"
cd "$tmp"
GIT_ADD_STORED=""
function git-mv-store
{
from="$(echo "$1" | sed 's/\./\\./')"
to="$(echo "$2" | sed 's/\./\\./')"
GIT_ADD_STORED+='s,\t'"$from"',\t'"$to"',;'
}
# NOTICE! This paths used for example! Use yours instead!
git-mv-store 'public/index.php' 'public/admin.php'
git-mv-store 'public/data' 'public/x/_data'
git-mv-store 'public/.htaccess' '.htaccess'
git-mv-store 'core/config' 'config/config'
git-mv-store 'core/defines.php' 'defines/defines.php'
git-mv-store 'README.md' 'doc/README.md'
git-mv-store '.gitignore' 'unneeded/.gitignore'
git filter-branch --index-filter '
git ls-files -s |
sed "'"$GIT_ADD_STORED"'" |
GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
' HEAD
GIT_ADD_STORED=""
cd "$path"
git remote add -f "$remote" "file://$tmp/.git"
git pull "$remote/master"
git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
git remote remove "$remote"
rm -rf "$tmp"
공지 사항
경로는 via를 대체 sed
하므로 병합 후 올바른 경로로 이동했는지 확인하십시오.
이 --allow-unrelated-histories
매개 변수는 git> = 2.9 이후에만 존재합니다.
조금 더 간단하다고 생각되는 다른 대답을 추가하십시오. repo_dest 풀은 repo_to_import로 완료된 후 push --set-upstream url : repo_dest 마스터가 수행됩니다.
이 방법은 여러 개의 작은 저장소를 더 큰 저장소로 가져 오는 데 효과적이었습니다.
가져 오는 방법 : repo1_to_import to repo_dest
# checkout your repo1_to_import if you don't have it already
git clone url:repo1_to_import repo1_to_import
cd repo1_to_import
# now. pull all of repo_dest
git pull url:repo_dest
ls
git status # shows Your branch is ahead of 'origin/master' by xx commits.
# now push to repo_dest
git push --set-upstream url:repo_dest master
# repeat for other repositories you want to import
가져 오기 전에 파일과 디렉토리의 이름을 원래 위치에서 원하는 위치로 바꾸거나 이동하십시오. 예 :
cd repo1_to_import
mkdir topDir
git add topDir
git mv this that and the other topDir/
git commit -m"move things into topDir in preparation for exporting into new repo"
# now do the pull and push to import
다음 링크에서 설명 된 방법이이 답변에 영감을주었습니다. 더 단순 해 보였기 때문에 마음에 들었습니다. 그러나 조심하십시오! 용이있다! https://help.github.com/articles/importing-an-external-git-repository git push --mirror url:repo_dest
는 로컬 리포지토리 기록 및 상태를 원격 (url : repo_dest)으로 푸시합니다. 그러나 원격의 이전 기록과 상태를 삭제합니다. 재미있다! :-이자형
필자의 경우 다른 저장소 (XXX)에서 일부 파일 만 가져오고 싶었습니다. 하위 트리가 너무 복잡하여 다른 솔루션이 작동하지 않았습니다. 이것이 내가 한 일입니다.
ALL_COMMITS=$(git log --reverse --pretty=format:%H -- ZZZ | tr '\n' ' ')
이것은 가져오고 자하는 파일 (ZZZ)에 영향을 미치는 모든 커밋의 공백으로 구분 된 목록을 역순으로 제공합니다 (이름 변경을 캡처하려면 --follow를 추가해야 할 수도 있음). 그런 다음 대상 리포지토리 (YYY)로 이동하여 다른 리포지토리 (XXX)를 원격으로 추가하고 가져 왔습니다.
git cherry-pick $ALL_COMMITS
이것은 모든 커밋을 브랜치에 추가하므로 히스토리가있는 모든 파일을 갖게되며 마치이 저장소에 항상있는 것처럼 원하는 파일을 처리 할 수 있습니다.
나는 찾고 있던 상황에 -s theirs
있었지만 물론이 전략은 존재하지 않습니다. 내 역사는 내가 GitHub에서 프로젝트를 분기 한 것이 었는데, 어떤 이유로 든 이 지점에 로컬 변경을하지 않았지만 어떤 이유로 로컬을 master
병합 할 수 upstream/master
없었습니다. (실제로 무슨 일이 있었는지 모릅니다. 업스트림이 무대 뒤에서 더러운 푸시를 한 것 같습니다.)
내가 끝낸 것은
# as per https://help.github.com/articles/syncing-a-fork/
git fetch upstream
git checkout master
git merge upstream/master
....
# Lots of conflicts, ended up just abandonging this approach
git reset --hard # Ditch failed merge
git checkout upstream/master
# Now in detached state
git branch -d master # !
git checkout -b master # create new master from upstream/master
이제 내 master
동기화가 다시 동기화됩니다 upstream/master
(동기화하려는 다른 지점에 대해서도 위의 과정을 반복 할 수 있습니다).
참조 기본 예제 에서 이 문서 와 저장소에 같은 매핑을 고려 :
A
<->YYY
,B
<->XXX
이 장에서 설명 된 모든 활동 후 (병합 후) branch를 제거하십시오 B-master
.
$ git branch -d B-master
그런 다음 변경 사항을 푸시하십시오.
그것은 나를 위해 작동합니다.
문제에 대한 다른 해결책 ( git-submodules 대신)을 제안 할 수 있습니다 - 길 (git links) 도구
복잡한 자식 리포지토리 종속성을 설명하고 관리 할 수 있습니다.
또한 git 재귀 하위 모듈 종속성 문제에 대한 솔루션을 제공합니다 .
다음과 같은 프로젝트 종속성이 있다고 가정하십시오. 샘플 git 저장소 종속성 그래프
그런 다음 .gitlinks
리포지토리 관계 설명으로 파일을 정의 할 수 있습니다 .
# Projects
CppBenchmark CppBenchmark https://github.com/chronoxor/CppBenchmark.git master
CppCommon CppCommon https://github.com/chronoxor/CppCommon.git master
CppLogging CppLogging https://github.com/chronoxor/CppLogging.git master
# Modules
Catch2 modules/Catch2 https://github.com/catchorg/Catch2.git master
cpp-optparse modules/cpp-optparse https://github.com/weisslj/cpp-optparse.git master
fmt modules/fmt https://github.com/fmtlib/fmt.git master
HdrHistogram modules/HdrHistogram https://github.com/HdrHistogram/HdrHistogram_c.git master
zlib modules/zlib https://github.com/madler/zlib.git master
# Scripts
build scripts/build https://github.com/chronoxor/CppBuildScripts.git master
cmake scripts/cmake https://github.com/chronoxor/CppCMakeScripts.git master
각 줄은 git link를 다음 형식으로 설명합니다.
- 저장소의 고유 이름
- 저장소의 상대 경로 (.gitlinks 파일 경로에서 시작)
- git clone 명령에서 사용할 Git 저장소 저장소 브랜치
- 빈 줄이나 #으로 시작하는 줄은 구문 분석되지 않습니다 (주석으로 처리).
마지막으로 루트 샘플 저장소를 업데이트해야합니다.
# Clone and link all git links dependencies from .gitlinks file
gil clone
gil link
# The same result with a single command
gil update
결과적으로 필요한 모든 프로젝트를 복제하고 적절한 방식으로 서로 연결합니다.
하위 링크 리포지토리의 모든 변경 사항이있는 일부 리포지토리의 모든 변경 내용을 커밋하려면 단일 명령으로 수행 할 수 있습니다.
gil commit -a -m "Some big update"
풀, 푸시 명령은 비슷한 방식으로 작동합니다.
gil pull
gil push
Gil (git links) 도구는 다음 명령을 지원합니다.
usage: gil command arguments
Supported commands:
help - show this help
context - command will show the current git link context of the current directory
clone - clone all repositories that are missed in the current context
link - link all repositories that are missed in the current context
update - clone and link in a single operation
pull - pull all repositories in the current directory
push - push all repositories in the current directory
commit - commit all repositories in the current directory
자식 재귀 하위 모듈 종속성 문제 에 대해 자세히 알아보십시오 .
나는 그것을하는 쉬운 방법을 모른다. 당신은 이것을 할 수 있습니다 :
- git filter-branch를 사용하여 XXX 저장소에 ZZZ 슈퍼 디렉토리를 추가하십시오.
- 새 분기를 YYY 저장소로 푸시하십시오.
- 푸시 된 브랜치를 YYY의 트렁크와 병합합니다.
매력적으로 들리면 세부 사항으로 편집 할 수 있습니다.
'git mv'와 'git pull'을 사용 하여이 작업을 수행 할 수 있다고 생각합니다.
나는 공정한 멍청한 놈이다-그래서 당신의 주요 저장소에주의하십시오-그러나 나는 단지 임시 디렉토리에서 이것을 시도했고 그것은 효과가있는 것 같습니다.
먼저-YYY 내에있을 때의 모양과 일치하도록 XXX의 구조 이름을 바꿉니다.
cd XXX
mkdir tmp
git mv ZZZ tmp/ZZZ
git mv tmp ZZZ
이제 XXX는 다음과 같습니다.
XXX
|- ZZZ
|- ZZZ
이제 'git pull'을 사용하여 변경 사항을 가져옵니다.
cd ../YYY
git pull ../XXX
이제 YYY는 다음과 같습니다.
YYY
|- ZZZ
|- ZZZ
|- (other folders that already were in YYY)
참고 URL : https://stackoverflow.com/questions/1683531/how-to-import-existing-git-repository-into-another
'Programming' 카테고리의 다른 글
Server.MapPath (“.”), Server.MapPath (“~”), Server.MapPath (@“\”), Server.MapPath (“/”). (0) | 2020.02.17 |
---|---|
RVM을 제거하는 방법? (0) | 2020.02.17 |
배쉬에서 숫자 비교 (0) | 2020.02.17 |
안드로이드 : 보이지 않는 것과 사라진 것의 차이점은 무엇입니까? (0) | 2020.02.17 |
CSS를 사용하는 다른 테이블 행 색상? (0) | 2020.02.17 |