[git] 한 분기를 다른 분기처럼 만드는 git 명령

변경 사항이있는 분기를 가져 와서 분기 된 업스트림과 동일하게 되돌리려 고합니다. 변경 사항은 로컬이며 github 로 푸시되었으므로 이미 푸시 된 브랜치에서는 나쁜 일인 기록을 변경 하기 때문에 둘 다 git reset또는 git rebase실제로 실행 가능 하지 않습니다 .

나는 또한 git merge다양한 전략을 시도했지만 그들 중 어느 것도 로컬 변경을 취소하지 않았습니다. 즉, 파일을 추가 한 경우 병합으로 다른 파일을 다시 가져올 수 있지만 업스트림이 수행하지 않는 파일은 계속 유지됩니다. 있다.

업스트림에서 새 분기를 만들 수는 있지만 수정 기록 측면에서 모든 변경 사항을 적용하여 분기를 가져와 다시 업스트림과 동일하게 만들어 해당 변경 사항을 안전하게 푸시 할 수 있도록 병합하고 싶습니다. 역사를 방해하지 않고. 그러한 명령이나 일련의 명령이 있습니까?



답변

당신은 당신의 상류 지점을 병합 할 수 dev으로, 지점 사용자 정의 병합 드라이버 “keepTheirs” :
페이지의 ” git merge -s theirs“-하지만 존재하지 않는 알 필요 “.
귀하의 경우에는 하나만 .gitattributes필요하며 다음과 같은 keepTheirs스크립트 가 필요합니다 .

mv -f $3 $2
exit 0

git merge --strategy=theirs 시뮬레이션 # 1

첫 번째 상위가 업스트림 인 병합으로 표시됩니다.

Jefromimerge -s ours업스트림 (또는 업스트림에서 시작하는 임시 분기)에서 작업을 병합 한 다음 해당 병합의 결과로 분기를 빠르게 전달하여 주석에서를 언급합니다 .

git checkout -b tmp origin/upstream
git merge -s ours downstream         # ignoring all changes from downstream
git checkout downstream
git merge tmp                        # fast-forward to tmp HEAD
git branch -D tmp                    # deleting tmp

이는 업스트림 조상을 첫 번째 부모로 기록하는 이점이 있으므로 병합은 “이 주제 브랜치를 파괴하고 업스트림으로 교체”하는 대신 “이 오래된 주제 브랜치를 흡수”하는 것을 의미 합니다.

(2011 년 편집) :

이 워크 플로는 OP에 의해이 블로그 게시물에 보고되었습니다 .

왜 이걸 다시 원합니까?

내 저장소가 공개 버전과 관련이없는 한 괜찮 았지만 이제는 WIP에서 다른 팀 구성원 및 외부 기여자와 공동 작업 할 수있는 기능을 원했기 때문에 공개 분기가 다른 사람들이 분기하고 가져올 수 있습니다. 즉, 이제 GitHub 및 공개에 있으므로 원격 백업에 푸시 한 항목을 더 이상 리베이스하거나 재설정 할 필요가 없습니다.

그래서 내가 어떻게 진행해야할지 남깁니다.
99 %의 시간 동안 내 사본이 업스트림 마스터로 이동하므로 대부분의 시간 동안 내 마스터를 작업하고 업스트림으로 푸시하고 싶습니다.
그러나 가끔씩, 내가 가진 것은 wip업스트림으로 들어가는 것에 의해 무효화되고 내 wip.
이 시점에서 마스터를 업스트림과 다시 동기화하고 싶지만 공개적으로 푸시 된 마스터의 커밋 포인트를 파괴하지는 않습니다. 즉, 업스트림과 동일한 복사본을 만드는 변경 집합으로 끝나는 업스트림과의 병합을 원합니다 .
그리고 그것이 git merge --strategy=theirs해야 할 일입니다.


git merge --strategy=theirs 시뮬레이션 # 2

첫 번째 부모로 우리와 병합으로 표시됩니다.

( jcwenger 제안 )

git checkout -b tmp upstream
git merge -s ours thebranch         # ignoring all changes from downstream
git checkout downstream
git merge --squash tmp               # apply changes from tmp but not as merge.
git rev-parse upstream > .git/MERGE_HEAD #record upstream 2nd merge head
git commit -m "rebaselined thebranch from upstream" # make the commit.
git branch -D tmp                    # deleting tmp

git merge --strategy=theirs 시뮬레이션 # 3

블로그 게시물에 언급 된 내용 :

git merge -s ours ref-to-be-merged
git diff --binary ref-to-be-merged | git apply -R --index
git commit -F .git/COMMIT_EDITMSG --amend

때때로 당신은 이것을 하기를 원합니다. 당신의 역사에 “쓰레기”가있어서가 아니라 아마도 리베이스를 피해야하는 공용 저장소에서 개발을위한 기준을 변경하기를 원하기 때문일 것 입니다.


git merge --strategy=theirs 시뮬레이션 # 4

(동일한 블로그 게시물)

또는 로컬 업스트림 분기를 빨리 감기 가능하게 유지하려는 경우 잠재적 인 타협은 sid / 불안정한 경우 업스트림 분기가 수시로 재설정 / 재 기반 될 수 있다는 이해와 함께 작업하는 것입니다 (최종적으로 종료되는 이벤트를 기반으로 함). 업스트림 프로젝트 측에 대한 제어).
이것은 큰 문제가 아니며 그 가정에 따라 작업한다는 것은 로컬 업스트림 분기를 빠른 업데이트 만받는 상태로 유지하는 것이 쉽다는 것을 의미합니다.

git branch -m upstream-unstable upstream-unstable-save
git branch upstream-unstable upstream-remote/master
git merge -s ours upstream-unstable
git diff --binary ref-to-be-merged | git apply -R --index --exclude="debian/*"
git commit -F .git/COMMIT_EDITMSG --amend

git merge --strategy=theirs 시뮬레이션 # 5

( Barak A. Pearlmutter 제안 ) :

git checkout MINE
git merge --no-commit -s ours HERS
git rm -rf .
git checkout HERS -- .
git checkout MINE -- debian # or whatever, as appropriate
git gui # edit commit message & click commit button

git merge --strategy=theirs 시뮬레이션 # 6

(동일한 Michael Gebetsroither가 제안 ) :

Michael Gebetsroither는 내가 “속임수”라고 주장하면서 차를 댔고;) 낮은 수준의 배관 명령으로 또 다른 해결책을 제시했습니다.

(git 전용 명령으로 가능하지 않다면 git이 아닙니다. diff / patch / apply를 사용하는 git의 모든 것은 실제 솔루션이 아닙니다.)

# get the contents of another branch
git read-tree -u --reset <ID>
# selectivly merge subdirectories
# e.g superseed upstream source with that from another branch
git merge -s ours --no-commit other_upstream
git read-tree --reset -u other_upstream     # or use --prefix=foo/
git checkout HEAD -- debian/
git checkout HEAD -- .gitignore
git commit -m 'superseed upstream source' -a

git merge --strategy=theirs 시뮬레이션 # 7

필요한 단계는 다음과 같이 설명 할 수 있습니다.

  1. 작업 트리를 업스트림으로 교체
  2. 인덱스에 변경 사항 적용
  3. 두 번째 상위 항목으로 업스트림 추가
  4. 범하다

이 명령 git read-tree두 번째 단계를 수행하는 다른 트리로 색인을 덮어 쓰고 첫 번째 단계를 수행하는 작업 트리를 업데이트하는 플래그를 갖습니다 . 커밋 할 때 git은 .git / MERGE_HEAD의 SHA1을 두 번째 부모로 사용하므로이를 채워 병합 커밋을 만들 수 있습니다. 따라서 다음을 사용하여 수행 할 수 있습니다.

git read-tree -u --reset upstream                 # update files and stage changes
git rev-parse upstream > .git/MERGE_HEAD          # setup merge commit
git commit -m "Merge branch 'upstream' into mine" # commit


답변

당신이해야 할 일처럼 들립니다.

$ git reset --hard origin/master

업스트림을 푸시 할 변경 사항이없고 단순히 업스트림 분기를 현재 분기로 설정하려는 경우 이렇게하면됩니다. 로컬에서이 작업을 수행하는 것은 해롭지 않지만 마스터로 푸시되지 않은 로컬 변경 **은 손실됩니다.

** 실제로 로컬로 커밋 한 경우 변경 사항은 여전히 ​​남아 있습니다. 커밋은 git reflog일반적으로 최소 30 일 동안.


답변

이제 쉽게 할 수 있습니다.

$ git fetch origin
$ git merge origin/master -s recursive -Xtheirs

이렇게하면 로컬 저장소가 오리진과 동기화되고 기록이 보존됩니다.


답변

다음에 대한 또 다른 시뮬레이션 git merge -s theirs ref-to-be-merged:

git merge --no-ff -s ours ref-to-be-merged         # enforce a merge commit; content is still wrong
git reset --hard HEAD^2; git reset --soft HEAD@{1} # fix the content
git commit --amend

이중 재설정의 대안은 리버스 패치를 적용하는 것입니다.

git diff --binary ref-to-be-merged | git apply -R --index


답변

배관 명령의 도움이 거의없는 방법도 있습니다. IMHO가 가장 간단합니다. 2 개의 브랜치 케이스에 대해 “theirs”를 에뮬레이트하고 싶다고 가정 해 보겠습니다.

head1=$(git show --pretty=format:"%H" -s foo)
head2=$(git show --pretty=format:"%H" -s bar)
tree=$(git show --pretty=format:"%T" -s bar)
newhead=$(git commit-tree $tree -p $head1 -p $head2 <<<"merge commit message")
git reset --hard $newhead

이것은 임의의 수의 헤드 (위의 예에서 2)를 병합하고, diff / file 문제를 무시하고 (커밋 트리는 저수준 명령이므로) 그중 하나의 트리 (위의 예에서는 bar, ‘그들의’트리 제공)를 사용합니다. 그것들은 신경 쓰지 않습니다). head는 1 일 수 있습니다 ( “theirs”가 포함 된 cherry-pick과 동일).

어떤 부모 헤드가 먼저 지정되는지는 일부 항목에 영향을 미칠 수 있습니다 (예 : git-log 명령의 –first-parent 참조). 따라서이를 염두에 두십시오.

git-show 대신, 트리 및 커밋 해시를 출력 할 수있는 다른 모든 것이 사용될 수 있습니다. 어떤 것이 든 파싱에 사용됩니다 (cat-file, rev-list, …). 커밋 메시지를 대화식으로 아름답게하기 위해 git commit –amend로 모든 것을 따를 수 있습니다.


답변

헤비 핸드이지만 지옥, 무엇이 잘못 될 수 있습니까?

  • Y처럼 보이고 싶은 지점 X를 확인하십시오.
  • cp -r .git /tmp
  • 지점 Y 확인 git checkout y
  • rm -rf .git && cp -r /tmp/.git .
  • 차이를 약속하고 추진하십시오
  • 끝난.


답변

원격 업스트림 분기로 변경 git merge하고 병합 전략을 ours.

git checkout origin/master
git merge dev --strategy=ours
git commit ...
git push

모든 기록은 여전히 ​​존재하지만 추가 병합 커밋이 있습니다. 여기서 중요한 것은 원하는 버전에서 시작하여 oursgithub가 실제로있는 지점 과 병합 하는 것입니다.