파일 히스토리를 깨지 않고 두 개의 Git 리포지토리 병합 지침을 따릅니다. 이전

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

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



답변

두 리포지토리를 함께 붙이고 외부 종속성을 관리하는 것이 아니라 모든 방식으로 보이도록하면 대답이 훨씬 간단합니다. 원격 저장소를 기존 저장소에 추가하고 새 저장소에 병합하고 파일 및 폴더를 하위 디렉토리로 이동 한 다음 이동을 커밋하고 모든 추가 저장소에 대해 반복하면됩니다. 하위 모듈, 하위 트리 병합 및 고급 rebase는 약간 다른 문제를 해결하기 위해 만들어졌으며 내가하려는 일에 적합하지 않습니다.

다음은 두 개의 저장소를 서로 연결하는 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
git remote add -f 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 (새로운 결합 저장소가 됨)로 병합하는 대신 스크립트를 수정하십시오.

진행중인 기능 분기를 가져 오려면 다음을 사용하십시오.

# 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가 계속 유효합니다. 결과적으로 두 번째 리포지토리의 파일은 하위 디렉토리에있게됩니다.

  1. 두 번째 저장소를 원격으로 추가하십시오.

    cd firstgitrepo/
    git remote add secondrepo username@servername:andsoon
    
  2. 두 번째 repo의 커밋을 모두 다운로드했는지 확인하십시오.

    git fetch secondrepo
    
  3. 두 번째 리포지토리에서 로컬 브랜치를 만듭니다.

    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
    

저장소에 루트 커밋이 두 개 이상 있지만 문제가되지는 않습니다.


답변

몇 년이 지났고 잘 기반을 둔 투표 솔루션이 있지만 이전 저장소의 기록을 삭제하지 않고 2 개의 원격 저장소를 새 저장소로 병합하고 싶기 때문에 조금 다릅니다 .

  1. Github에서 새 저장소를 만듭니다.

    여기에 이미지 설명을 입력하십시오

  2. 새로 작성된 저장소를 다운로드하고 이전 원격 저장소를 추가하십시오.

    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. 마스터 브랜치에서 병합을 수행하여 이전 리포지토리를 새로 생성 된 리포지토리와 결합하십시오.

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

    여기에 이미지 설명을 입력하십시오

  5. OldRepo에서 추가 된 모든 새로 작성된 컨텐츠를 저장하고 파일을이 새 폴더로 이동하려면 새 폴더를 작성하십시오.

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

이것이 원격 저장소 병합을 다루는 모든 사람에게 유용 할 수 있기를 바랍니다.


답변

사용을 살펴보십시오

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

삶의 초기에 두 역사를 연결합니다.

경로가 겹치는 경우 다음과 같이 수정하십시오.

git filter-branch --index-filter

로그를 사용할 때 다음을 사용하여 “복사본 찾기”를 확인하십시오.

git log -CC

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


답변

@Flimm 의 솔루션 을 다음 git alias과 같이 (내 추가 ~/.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"


답변

이 기능은 원격 저장소를 로컬 저장소로 복제합니다.

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 history를 갖는 한 repo를 다른 repo에 포함시키는 단계를 따르십시오.

  1. 병합하려는 리포지토리를 모두 복제하십시오.

자식 클론 git@github.com : user / parent-repo.git

자식 클론 git@github.com : user / child-repo.git

  1. 아동 저장소로 이동

CD 아동 레포 /

  1. 아래 명령을 실행하고 경로 my/new/subdir(3 발생)를 하위 저장소를 원하는 디렉토리 구조로 바꾸십시오 .

git filter-branch –prune-empty –tree-filter ‘if [! -e my / new / subdir]; mkdir -p my / new / subdir git ls-tree-이름 만 $ GIT_COMMIT | xargs -I 파일 mv 파일 my / new / subdir fi ‘

  1. 부모 저장소로 이동

cd ../parent-repo/

  1. 하위 리포지토리에 대한 경로를 가리키는 상위 리포지토리에 원격 추가

자식 원격 추가 자식 원격 ../child-repo/

  1. 아이 레포를 가져옵니다

자식 원격 가져 오기 자식

  1. 역사를 병합

git merge-관련이없는 아이의 원격 / 마스터를 허용

부모 리포지토리에서 git 로그를 확인하면 자식 리포지토리가 병합되어야합니다. 커밋 소스에서 나타내는 태그를 볼 수도 있습니다.

아래 기사는 두 리포지토리를 병합하여 하나의 단일 리포지토리를 갖는 한 리포지를 다른 리포에 포함시키는 데 도움이되었습니다.

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

도움이 되었기를 바랍니다. 행복한 코딩!