programing

파일 기록을 중단하지 않고 두 Git 저장소 병합

oldcodes 2023. 5. 9. 22:59
반응형

파일 기록을 중단하지 않고 두 Git 저장소 병합

두 개의 Git 저장소를 새로운 세 번째 저장소로 병합해야 합니다.하위 트리 병합을 사용하여 이 작업을 수행하는 방법에 대한 많은 설명을 찾았습니다(예: 두 Git 저장소병합하는 방법에 대한 Jakub Naręski의 답변). 이러한 지침을 따르는 것은 하위 트리 병합을 커밋할 때 이전 저장소의 모든 파일이 새 추가된 파일로 기록된다는 점을 제외하고 대부분 작동합니다.그러면 이전 리포지토리에서 커밋 기록을 볼 수 있습니다.git log하지만 내가 한다면,git log <file>해당 파일에 대한 하나의 커밋(하위 트리 병합)만 표시됩니다.위의 답변에 대한 의견으로 판단해 볼 때, 저는 이 문제를 보는 유일한 사람이 아니지만 이에 대한 공개된 해결책을 찾지 못했습니다.

리포지토리를 병합하고 개별 파일 기록을 그대로 유지할 수 있는 방법이 있습니까?

외부 종속성을 관리하는 대신 두 개의 저장소를 결합하여 전체적으로 그렇게 보이도록 하는 것이 훨씬 더 간단합니다.이전 리포지토리에 원격을 추가하고 새 마스터에 병합한 다음 파일과 폴더를 하위 디렉터리로 이동하고 이동을 커밋한 다음 모든 추가 리포지토리에 대해 반복하기만 하면 됩니다.서브모듈, 서브트리 병합 및 고급 리베이스는 약간 다른 문제를 해결하기 위한 것으로 제가 하려고 했던 것에 적합하지 않습니다.

다음은 두 개의 리포지토리를 결합하는 Powershell 스크립트의 예입니다.

# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init

# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
git commit --allow-empty -m "Initial dummy commit"

# Add a remote for and fetch the old repo
# (the '--fetch' (or '-f') option will make git immediately fetch commits to the local repo after adding the remote)
git remote add --fetch old_a <OldA repo URL>

# Merge the files from old_a/master into new/master
git merge old_a/master --allow-unrelated-histories

# Move the old_a repo files and folders into a subdirectory so they don't collide with the other repo coming later
mkdir old_a
dir -exclude old_a | %{git mv $_.Name old_a}

# Commit the move
git commit -m "Move old_a files into subdir"

# Do the same thing for old_b
git remote add -f old_b <OldB repo URL>
git merge old_b/master --allow-unrelated-histories
mkdir old_b
dir –exclude old_a,old_b | %{git mv $_.Name old_b}
git commit -m "Move old_b files into subdir"

물론 그렇게 하고 싶다면 old_b를 old_a(새로 결합된 repo가 됨)에 병합할 수 있습니다. 스크립트를 적합하게 수정하십시오.

진행 중인 피쳐 분기도 가져오려면 다음을 사용합니다.

# Bring over a feature branch from one of the old repos
git checkout -b feature-in-progress
git merge -s recursive -Xsubtree=old_a old_a/feature-in-progress

이는 프로세스의 명백하지 않은 유일한 부분입니다. 하위 트리 병합이 아니라 일반 재귀 병합에 대한 인수입니다. 이 인수는 Git에게 대상의 이름을 변경하고 Git이 모든 것을 올바르게 정렬하는 데 도움이 됩니다.

저는 여기에 조금 더 자세한 설명을 적었습니다.

기록을 다시 작성하지 않는 방법이 있으므로 모든 커밋 ID는 유효합니다.결과적으로 두 번째 repo의 파일은 하위 디렉터리에 있게 됩니다.

  1. 두 번째 repo를 원격으로 추가합니다.

    cd firstgitrepo/
    git remote add secondrepo username@servername:andsoon
    
  2. 두 번째 보고서의 커밋을 모두 다운로드했는지 확인합니다.

    git fetch secondrepo
    
  3. 두 번째 repo의 분기에서 로컬 분기를 만듭니다.

    git branch branchfromsecondrepo secondrepo/master
    
  4. 모든 파일을 하위 디렉터리로 이동합니다.

    git checkout branchfromsecondrepo
    mkdir subdir/
    git ls-tree -z --name-only HEAD | xargs -0 -I {} git mv {} subdir/
    git commit -m "Moved files to subdir/"
    
  5. 두 번째 분기를 첫 번째 repo의 마스터 분기로 병합합니다.

    git checkout master
    git merge --allow-unrelated-histories branchfromsecondrepo
    

리포지토리에는 두 개 이상의 루트 커밋이 있지만 문제가 되지 않습니다.

를 병합하고 .a안으로b으)ㄹ 수 있습니다.

cd b
git remote add a ../a
git fetch a
git merge --allow-unrelated-histories a/master
git remote remove a

당신이 넣고 싶은 경우에.a하위 디렉터리로 위의 명령 앞에 다음을 수행합니다.

cd a
git filter-repo --to-subdirectory-filter a
cd ..

이를 위해 설치해야 합니다(filter-branch낙담함).

두 개의 큰 저장소를 병합하고 그 중 하나를 하위 디렉터리에 넣는 예: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731

자세한 내용은 여기 있습니다.

몇 년이 지났고, 잘 기반된 사전 투표 솔루션이 있지만 이전 저장소에서 기록을 삭제하지 않고 원격 저장소 2개를 새로운 저장소로 병합하고 싶었기 때문에 제 것을 공유하고 싶습니다.

  1. Github에 새 리포지토리를 만듭니다.

    여기에 이미지 설명 입력

  2. 새로 만든 repo를 다운로드하고 이전 원격 저장소를 추가합니다.

    git clone https://github.com/alexbr9007/Test.git
    cd Test
    git remote add OldRepo https://github.com/alexbr9007/Django-React.git
    git remote -v
    
  3. 새 분기가 생성되도록 이전 저장소에서 모든 파일을 가져옵니다.

    git fetch OldRepo
    git branch -a
    

    여기에 이미지 설명 입력

  4. 마스터 분기에서 병합을 수행하여 이전 repo를 새로 만든 repo와 결합합니다.

    git merge remotes/OldRepo/master --allow-unrelated-histories
    

    여기에 이미지 설명 입력

  5. 새 폴더를 만들어 이전 보고서에서 추가된 새로 작성된 모든 내용을 저장하고 해당 파일을 이 새 폴더로 이동합니다.

  6. 마지막으로, 결합된 저장소에서 파일을 업로드하고 GitHub에서 OldRepo를 안전하게 삭제할 수 있습니다.

원격 리포지토리 병합을 처리하는 모든 사용자에게 유용할 수 있기를 바랍니다.

를 사용해 보십시오.

git rebase --root --preserve-merges --onto

그들의 삶의 초기에 두 역사를 연결하는 것.

경로가 중복되는 경우 다음과 같이 수정합니다.

git filter-branch --index-filter

로그를 사용할 때는 "복사본을 더 어렵게" 찾으십시오.

git log -CC

그렇게 하면 경로에서 파일의 움직임을 찾을 수 있습니다.

저는 @Flimm this에서 솔루션을 하나로 만들었습니다.git alias 이렇게 (에나▁my))에 추가됨)~/.gitconfig):

[alias]
 mergeRepo = "!mergeRepo() { \
  [ $# -ne 3 ] && echo \"Three parameters required, <remote URI> <new branch> <new dir>\" && exit 1; \
  git remote add newRepo $1; \
  git fetch newRepo; \
  git branch \"$2\" newRepo/master; \
  git checkout \"$2\"; \
  mkdir -vp \"${GIT_PREFIX}$3\"; \
  git ls-tree -z --name-only HEAD | xargs -0 -I {} git mv {} \"${GIT_PREFIX}$3\"/; \
  git commit -m \"Moved files to '${GIT_PREFIX}$3'\"; \
  git checkout master; git merge --allow-unrelated-histories --no-edit -s recursive -X no-renames \"$2\"; \
  git branch -D \"$2\"; git remote remove newRepo; \
}; \
mergeRepo"

이 함수는 원격 repo를 로컬 repo로 복제합니다.

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

주의. 이 스크립트는 커밋을 다시 작성할 수 있지만 모든 작성자와 날짜를 저장합니다. 이는 새 커밋에 다른 해시가 있음을 의미하며, 원격 서버에 변경사항을 푸시하려고 하면 강제 키만 사용할 수 있으며 서버의 커밋도 다시 작성됩니다.따라서 시작하기 전에 백업을 작성하십시오.

이익!

두 Git 내역을 병합하여 하나의 Git 내역이 있는 하나의 repo를 다른 repo에 포함하는 단계를 수행합니다.

  1. 병합할 리포지토리를 모두 복제합니다.

git clone git@github.com :user/parent-repo.git

git clone git@github.com :user/child-repo.git

  1. 하위 레포로 이동

cd child-repo/

  1. 아래 명령 실행, 경로 바꾸기my/new/subdir(3회) 하위 repo를 사용할 디렉토리 구조를 사용합니다.

git filter-branch --prune-empty --tree-filter' if [! -emy/new/subdir]; mkdir -pmy/new/subdigits-tree --name 전용 $GIT_COMMIT | xargs -I files my/new/subdirfi'

  1. 상위 레포로 이동

cd ../parent-repo/

  1. 부모 repo에 원격 추가, 자식 repo에 경로 지정

git remote child-remote 추가 ../child-repo/

  1. 하위 레포 가져오기

git fetch child-remote

  1. 기록 병합

git merge --allow-message-message 하위-원격/마스터

지금 상위 보고서에서 Git 로그를 확인하면 하위 보고서 커밋이 병합됩니다.커밋 원본을 나타내는 태그도 볼 수 있습니다.

아래 기사는 두 Git 이력을 병합하여 하나의 Git 이력을 하나의 Repo를 다른 Repo에 포함하는 데 도움이 되었습니다.

http://ericlathrop.com/2014/01/combining-git-repositories/

이게 도움이 되길 바랍니다.해피 코딩!

filter-repo를 사용하는 x-yuri의 답변을 기반으로 몇 가지 스크립트로 Repository를 만들었습니다.스크립트를 사용하면 다른 하위 디렉터리를 지정하면 병합 충돌 없이 모든 분기와 태그를 새 리포지토리로 쉽게 이동할 수 있습니다.

언급URL : https://stackoverflow.com/questions/13040958/merge-two-git-repositories-without-breaking-file-history

반응형