2014-01-19 6 views
7

에없는 어떤 커밋 :제거는 실제로 두 개의 저장소가 하위 트리에도 원래 저장소

  • main
  • main 저장소는 (external/main 디렉토리에 잠시 후 합병 external

하위 트리로). 이제 external/main에 대한 변경 사항을 main 리포지토리로 마이그레이션하고 싶지만이 커밋과 external/<anything-else>과 같은 다른 관련없는 커밋 만 리포지토리로 마이그레이션하고 싶습니다.

git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter main -- --all 

을하지만 너무 초기 main 저장소에 대한 모든 커밋을 제거하고 오직 external 자식 저장소에 만들어진 것들 잎 :

는 사실은 고전을 시도했습니다.


그래서 : 오직 커밋 유지하는 방법 :

A)

B)는 external의 하위 트리에 만들어진 초기 main 저장소에 만들어진 (external/main를)


git pull -s subtree ../external을 시도하면 하위 트리에서 아무 것도 변경하지 않은 커밋을 포함하여 커밋이 모두 병합됩니다. 하위 트리의 내용을 실제로 변경 한 커밋과 하위 트리의 파일에 대한 정보 만 필요합니다.

+0

'ZZZ'는 어떻게'AAA'에 병합 되었습니까? – LopSae

+0

또한 약간의 의미를 전달하는 이름을 사용할 수 있습니다. 예를 들어 리포지토리의 경우 'main'과'external'와 같이 질문의 가독성을 높이는 데 도움이됩니다. – LopSae

+0

일반적인 메커니즘 :'external'에서 repo를 가져 와서'read-tree '를 사용하여'external' repo의 디렉토리에 넣습니다. – bwoebi

답변

2

당신은 당신의 명령의 <rev-list options> 섹션에 --not --remotes를 사용 filter-branch에 의해 다시 커밋을 제한 할 수 있어야한다 : 이것은 원격 지점에서 도달 커밋을 포함하지 아니하는 filter-branch의 원인이됩니다

git filter-branch --tag-name-filter cat --prune-empty 
    --subdirectory-filter main -- --all --not --remotes 

. 리모컨이 여러 개인 경우 --remotes=origin과 같은 것을 사용하여 고려해야 할 리모컨을 지정할 수 있습니다.

+0

음 ... 아주 좋습니다! 감사! 그냥 어떻게 든 다른 관련없는 하위 트리 병합 커밋을 포함 : https://github.com/krakjoe/phpdbg/commit/efc7d6db18a4f5ecc6c4437041c78f067c96e05d 어떤 생각이 그것을 제거하는 ... 어떻게 든 문제를 일으키는 지점의 루트 커밋되었다 ... – bwoebi

+0

@bwoebi 저장소에 익숙하지 않아서 여기서 일어난 일을 시각화하는 것이 어렵습니다. 현재 루트 커밋을 단순히 제거하려는 경우 [이 질문] (http://stackoverflow.com/questions/645450/git-how-to-insert-a-commit-as-the- first- shifting-all-the-others), 여기서 답은 모든 커밋을 새로운 * empty * root 커밋으로 다시 작성하는 방법을 보여줍니다. 이제'rebase -i'를 사용하여 오래된 루트 (이제 두 번째 커밋)를 삭제할 수 있습니다. – Chris

+1

음 ... 그게 도움이되지 않았지만, http://stackoverflow.com/a/6149972/2153758 않았다. 어쨌든 고맙습니다 ... 현상금을받을 자격이 있습니다. – bwoebi

1

발생해야합니다 external 두 가지에서 일어난 main 모든 관련 변경에 가져하기 위해서 :

  • 원래 main
  • external
  • 에서 일어난 모든 커밋 main에 가져와 분리

처음에는 원본을 분리하십시오 main :

아마도 자신의 저장소에 main이있는 것 같습니다.

원래 mainexternal/main 서브 디렉토리를 작성한 확약의 상위로 설정된 경우에만 external 저장소에서 검색 될 수 있습니다. 그러한 예는 Git Book Subtree Merging page

에 설명 된 프로세스입니다. 여기서 소개 된 하위 트리는 in this answer과 같습니다.

그리고 나서 main의 자료 인 전체 커밋 집합을 잡아서 저장소를 만들어야합니다. 두 번째의 경우


, main에 가져와 그것을 external에서 일어난 모든 커밋 :

당신은 이미 exteral/main 하위 폴더에 변경 사항이 포함 커밋을 고립,하지만 당신이 상태로는 포함되어 있지 않습니다

원래 main이 커밋됩니다. filter-branch 만 하위 디렉토리를 만든 read-tree처럼 더 복잡한 작업을 처리하는 방법을 모른 채, 특정 하위 디렉토리 위치에있는 파일을 확인하기 때문에

git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter main -- --all 

이다.

filter-branch 작업 후에는 main/external에 발생한 모든 변경 사항을 포함하는 커밋 집합이 남아있게됩니다. filteredMain 브랜치에서이 커밋 세트에 도달 할 수 있다고 가정 해 보겠습니다.

내용이 서브 디렉토리에서 루트로 이동되었으므로 파일의 위치는 이제 main 저장소의 내용과 동일합니다. 이렇게하면 두 나무가 결합됩니다. 이 두 트리 (main의 master 브랜치와 filterBranch)는 공통된 히스토리가 없기 때문에 커밋 변경을 재생하여 rebase을 결합 할 수 있습니다.

# in the main repository 

# bring the external repository and get the branch 
git remote add external /path/to/external 
git fetch external filteredMain 
git checkout filteredMain 

# We need the first commit of this tree for the rebase command 
firstCommit=$(git rev-list --max-parents=0 HEAD) 

# run the rebase 
git rebase --onto master $firstCommit filteredMain 

이 후 filteredMain 지점은 main 저장소에 원래 master 지점의 상단에 재생 external/main에서 일어난 모든 변경 사항을 포함해야합니다.

+0

은 유효한 대안처럼 보입니다. 그러나 실제로는 위의 대답은 a) 명령어가 적고 b) 한 지점에서만 작동하므로 훨씬 실용적입니다. – bwoebi

+0

단일 'filter-branch'명령을 사용하여'main' 커밋과'external/main'을 하나의 트리로 유지하는 방법을 알 수 없기 때문에이 문제를 잘못 이해했을 수도 있습니다. 어쨌든, 걱정할 필요가 없습니다. 저는 개인적인 호기심으로 며칠 동안이 답변을 작품에 남겼습니다. 질문이 이미 끝났다고해도 끝내기로했습니다. – LopSae