기존 Git 저장소를 다른 저장소로 가져오는 방법은 무엇입니까?
XXX라는 폴더에 Git 저장소가 있고 YYY라는 두 번째 Git 저장소가 있습니다.
XXX 저장소를 ZZZ라는 하위 디렉터리로 YY 저장소로 가져오고 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
저는 제 레포지트 몇 개로 이것을 시도해 보았는데 작동합니다.Jörg의 답변과 달리 다른 repo를 계속 사용할 수는 없지만, 어쨌든 당신은 그것을 명시하지 않았다고 생각합니다.
참고: 2009년에 작성된 이후로 git는 아래 답변에 언급된 하위 트리 병합을 추가했습니다.물론 이 방법은 여전히 효과가 있지만, 저는 아마 오늘날 그 방법을 사용할 것입니다.
두 번째 저장소의 정확한 커밋 기록을 유지하고 향후 업스트림 변경사항을 쉽게 병합할 수 있는 기능도 유지하려면 다음 방법을 사용합니다.그러면 하위 트리의 수정되지 않은 기록이 repo로 가져오고 병합된 리포지토리를 하위 디렉터리로 이동하는 병합 커밋이 하나씩 발생합니다.
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는 병합을 수행하기 전에 루트가 어디에 있는지 자체적으로 파악하므로 이후 병합 시 접두사를 지정할 필요가 없습니다.
단점은 병합된 기록에서 파일이 (하위 디렉터리가 아닌) 미리 고정되어 있지 않다는 것입니다.결과적으로.git log ZZZ/a병합된 기록을 제외한 모든 변경 사항(있는 경우)이 표시됩니다.수 있는 것은 다음과 같습니다.
git log --follow -- a
하지만 병합된 기록의 변경 내용은 표시되지 않습니다.
바꿔 말하면, 당신이 변하지 않는다면,ZZZ의 에 있습니다XXX "" "" " " " " 를 지정해야 .--follow그리고 고정되지 않은 경로.두 리포지토리 모두에서 변경할 경우 두 개의 명령이 있지만 모든 변경 내용을 표시하는 명령은 없습니다.
2.9 이전 Git 버전: 테스트를 통과할 필요가 없습니다.--allow-unrelated-histories에 대한 선택권.git merge.
에서 다을사다답방른을 사용하는 .read-tree그리고 건너뜁니다.merge -s ours이 없습니다. step은 cp와 함께 파일을 복사합니다.
원본 소스는 Github의 "Subtree Merge" 도움말 문서에서 가져온 것입니다.그리고 또 다른 유용한 링크.
git-subtree 기록을 보존하면서 여러 리포지토리를 하나로 병합하는 사용 사례를 위해 설계된 스크립트입니다(및/또는 하위 트리의 기록을 분할하는 것은 이 질문과 무관한 것으로 보입니다).릴리스 1.7.11 이후 깃 트리의 일부로 배포됩니다.
리포지토리를 병합하려면 다음과 같이 하십시오.<repo><rev> 디렉터리로<prefix>,사용하다git subtree add다음과 같이:
git subtree add -P <prefix> <repo> <rev>
git-intervree는 보다 사용자 친화적인 방식으로 하위 트리 병합 전략을 구현합니다.
이 경우 저장소 YYY에서 다음을 실행합니다.
git subtree add -P ZZZ /path/to/XXX.git master
단점은 병합된 기록에서 파일이 (하위 디렉터리가 아닌) 미리 고정되어 있지 않다는 것입니다.결과적으로.git log ZZZ/a병합된 기록을 제외한 모든 변경 사항(있는 경우)이 표시됩니다.수 있는 것은 다음과 같습니다.
git log --follow -- a
하지만 병합된 기록의 변경 내용은 표시되지 않습니다.
바꿔 말하면, 당신이 변하지 않는다면,ZZZ의 에 있습니다XXX "" "" " " " " 를 지정해야 .--follow그리고 고정되지 않은 경로.두 리포지토리 모두에서 변경할 경우 두 개의 명령이 있지만 모든 변경 내용을 표시하는 명령은 없습니다.
자세한 내용은 여기 있습니다.
Git 저장소 자체에 이러한 사례가 있으며, Git 커뮤니티에서 "가장 멋진 병합"(이 병합을 설명하는 Git 메일링 목록에 전자 메일에 사용된 제목 줄 Linus Torvalds의 이름을 따서)으로 통칭됩니다.이 경우,gitkGit GUI는 현재 Git property의 일부이지만, 실제로는 별도의 프로젝트였습니다.라이너스는 그 저장소를 Git 저장소로 통합하는 데 성공했습니다.
- 마치 항상 Git의 일부로 개발된 것처럼 Git 저장소에 나타납니다.
- 모든 역사는 온전하게 보존되어 있고,
- 여전히 오래된 저장소에서 독립적으로 개발할 수 있으며, 변경 사항은 단순히 다음과 같습니다.
git pull편집의
이메일에는 재생산에 필요한 단계가 포함되어 있지만, 심장이 약한 사람들을 위한 것은 아닙니다. 첫째, 리누스는 Git을 썼기 때문에 아마 당신이나 저보다 그것에 대해 조금 더 알고 있을 것이고, 둘째, 이것은 거의 5년 전의 일이고 Git이 그 이후로 상당히 발전했기 때문에 아마도 지금은 훨씬 더 쉬울 것입니다.
특히 요즘에는 특정한 경우에 Gitk 서브모듈을 사용할 것이라고 생각합니다.
▁names다▁use니 이름을 사용하겠습니다.a(XXX그리고.ZZZ및 ) 및b(YYY이 좀 쉽기 에.), 설을읽더조쉽때문니다입기명금기가▁),다니때입문▁since설▁thatription.
를 병합하고 .a안으로b으)ㄹ 수 있습니다.
cd a
git filter-repo --to-subdirectory-filter a
cd ..
cd b
git remote add a ../a
git fetch a
git merge --allow-unrelated-histories a/master
git remote remove a
이를 위해 설치해야 합니다(filter-branch낙담함).
두 개의 큰 저장소를 병합하고 그 중 하나를 하위 디렉터리에 넣는 예: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731
자세한 내용은 여기 있습니다.
이를 위한 간단한 방법은 git format-patch를 사용하는 것입니다.
2git 저장소 foo와 bar가 있다고 가정합니다.
foo 내용물:
- foot.txt
- .git
막대에 포함되는 내용:
- bar.txt
- .git
그리고 우리는 바 이력과 다음 파일이 포함된 foo로 마무리하고 싶습니다.
- foot.txt
- .git
- 푸바/바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 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의 파일/dir를 다음과 같은 다른 경로로 이동할 수도 있습니다.
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"
경로가 다음을 통해 대체됨sed병합 후 적절한 경로로 이동했는지 확인합니다.
그--allow-unrelated-histories매개 변수는 git >= 2.9 이후에만 존재합니다.
이 기사를 바탕으로 하위 트리를 사용하는 것이 저에게 효과가 있었고 적용 가능한 이력만 전송되었습니다.단계가 필요한 사람이 있을 경우 여기에 게시합니다(자리 표시자를 해당 값으로 교체하십시오).
원본 리포지토리에서 하위 폴더를 새 분기로 분할
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
소스 repo에서 데이터를 가져오기 위해 추가한 원격을 제거합니다.
git remote rm merge-source-repo
이것이 조금 더 간단하다고 생각하기 때문에 다른 답변을 추가합니다.repo_to_import로 repo_dest를 풀한 다음 --setupstream url:repo_dest master를 푸시합니다.
이 방법은 여러 개의 더 작은 저장소를 더 큰 저장소로 가져오는 데 효과가 있었습니다.
가져오는 방법: 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
가져오기 전에 파일 및 dir의 이름을 변경하거나 원래 repo에서 원하는 위치로 이동합니다. 예를 들어 이동합니다.
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_destrepo 파일은url:repo_dest 파일입니다. 그러나 됩니다.그러나 원격의 이전 기록과 상태를 삭제합니다.재미가 뒤따릅니다! :-E
여기 바로 작동할 스크립트가 있습니다.
#!/bin/bash -xe
# script name: merge-repo.sh
# To merge repositories into the current.
# To see the log of the new repo use 'git log --follow -- unprefixed-filename'
# So if the file is repo/test.cpp use 'git log --follow -- test.cpp'
# I'm not sure how this will work when two files have the same name.
#
# `git branch -a` will show newly created branches.
# You can delete them if you want.
merge_another() {
repo="$1" # url of the remote repo
rn="$2" # new name of the repo, you can keep the same name as well.
git remote add ${rn} ${repo}
git fetch ${rn}
git merge -s ours --no-commit --allow-unrelated-histories ${rn}/master
git read-tree --prefix=${rn}/ -u ${rn}/master
git commit -m "Imported ${rn} as a subtree."
git pull -s subtree ${rn} master
}
merge_another $1 $2
스크립트를 실행합니다.다른 레포를 병합할 레포로 이동하여 스크립트를 실행합니다.
cd base-repo
./merge-repo.sh git@github.com:username/repo-to-be-merged.git repo-to-be-merged-new-name
이제 마스터 분기의 변경 내용을 원격/원본으로 푸시합니다.이 단계는 수행하려는 작업에 따라 필요하지 않을 수 있습니다.
git push origin master
이 경우 다른 리포지토리(XXX)에서 일부 파일만 가져오려고 했습니다.하위 트리는 저에게 너무 복잡했고 다른 솔루션은 작동하지 않았습니다.제가 한 일은 이렇습니다.
ALL_COMMITS=$(git log --reverse --pretty=format:%H -- ZZZ | tr '\n' ' ')
이렇게 하면 가져올 파일(ZZ)에 영향을 주는 모든 커밋이 역순으로 공백으로 구분된 목록이 표시됩니다(이름을 캡처하려면 --follow도 추가해야 할 수 있습니다).그런 다음 대상 리포지토리(YYY)로 들어가 다른 리포지토리(XXX)를 원격으로 추가한 다음 해당 리포지토리에서 가져오기를 수행했습니다.
git cherry-pick $ALL_COMMITS
이렇게 하면 모든 커밋이 분기에 추가되므로 기록이 있는 모든 파일이 이 저장소에 항상 있었던 것처럼 파일로 원하는 작업을 수행할 수 있습니다.
이 문서의 기본 예제를 참조하고 리포지토리에 대한 이러한 매핑을 고려합니다.
A<->YYY,B<->XXX
장에서 후(마무리 후) 분기를 합니다.B-master:
$ git branch -d B-master
그런 다음 변경 사항을 푸시합니다.
저한테는 효과가 있어요.
저는 제가 찾고 있던 상황에 있었습니다.-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(또한 유사하게 동기화하려는 다른 분기에 대해서도 위의 내용을 반복할 수 있습니다.
나는 당신의 문제에 대한 다른 해결책(git-submodules의 대안)을 제안할 수 있습니다 - gil (git links) 도구.
복잡한 Git 저장소 종속성을 설명하고 관리할 수 있습니다.
또한 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
각 행은 다음 형식으로 깃 링크를 설명합니다.
- 리포지토리의 고유 이름
- 저장소의 상대 경로(.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 재귀 하위 모듈 종속성 문제에 대해 자세히 알아봅니다.
x-yuri의 답변에 댓글을 달기에는 rep가 부족하지만, 그것은 아름답게 작동하고 역사를 보존합니다.저는 두 명의 현지 담당자와 함께 일하고 있었는데 다음 오류를 받았습니다.
중단: 복원 기록이 새로 복제된 것처럼 보이지 않기 때문에 삭제적으로 덮어씁니다.(새로 포장된 repo가 예상됨) 대신 새 클론에서 작업하십시오.계속하려면 --force를 사용합니다.
그것의 영향에 대해 걱정하는 것보다.--force플래그, 다음을 사용하여 먼저 레포를 로컬로 복제했습니다.
cd tempDir
git clone <location of repo to be merged> --no-local
그리고 x-dump가 배치한 일련의 명령에 대해 이 새로 복제된 복사본을 사용했습니다.마지막으로, 다음 위치:git filter-repo --to-subdirectory-filter a,a가져올 repo의 루트 폴더에 지정하는 이름입니다.
저는 그것을 하는 쉬운 방법을 모릅니다.다음을 수행할 수 있습니다.
- git filter-branch를 사용하여 XXX 저장소에 ZZZ 슈퍼 디렉토리 추가
- 새 분기를 YYY 저장소로 푸시
- 푸시된 분기를 YYY의 트렁크와 병합합니다.
매력적으로 들리면 세부사항으로 편집할 수 있습니다.
'git mv'와 'git pull'을 사용하면 될 것 같습니다.
저는 공정한 사람입니다. 그러므로 당신의 주요 저장소를 조심하세요. 하지만 저는 임시로 이것을 시도했고 효과가 있는 것 같습니다.
먼저 XXX의 구조 이름을 YYY 내에 있을 때 원하는 모양과 일치하도록 변경합니다.
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
'programing' 카테고리의 다른 글
| SELECT * [열 A 제외]를 사용하여 열을 테이블 A에서 제외하시겠습니까? (0) | 2023.04.29 |
|---|---|
| Azure 웹 작업 및 배포 슬롯 (0) | 2023.04.29 |
| WPF의 페이지 대 창? (0) | 2023.04.29 |
| Angular 2.0 및 Modal 대화 상자 (0) | 2023.04.29 |
| 여기서 ${EXECUTABLE_NAME} 및 ${PRODUCT_NAME}은(는) 정의됩니다. (0) | 2023.04.29 |