저장소에서 파일을 지우는 Git 병합을 실행 취소하는 가장 좋은 방법은 무엇입니까?


13

따라서 다음과 같은 상황이 발생한다고 가정 해 봅시다 (우리 모두가 SourceTree를 사용하고 있음).

  1. 우리는 모두 원산지 / 개발을 진행하고 있습니다.
  2. 나는 일주일 동안 휴가를 간다.
  3. 내 동료는 지난 며칠 동안 현지 개발 지점에 원산지 / 개발을 병합하지 않고 현지에서 일하고 있습니다.
  4. 그는 밀어 넣기를 시도하고 먼저 병합해야한다는 말을 듣습니다.
  5. 충돌이 발생하여 병합 후 자동 커밋이 진행되지 않습니다.
  6. Git이 SVN과 같다고 가정하면 동료는 작업 복사본에서 "새"파일을 버린 다음 병합을 커밋하여 해당 "새"파일을 원산지 / 개발 책임자로부터 삭제합니다.
  7. 그 개정판에는 몇 주 동안의 개발 작업이 진행됩니다.
  8. 나는 휴일에서 돌아와서 며칠간의 작업이 누락되었음을 알게됩니다.

우리는 모두 Git을 처음 접했지만 (이 프로젝트를 사용하는 첫 번째 프로젝트), 내가 고 쳤던 것은 다음과 같습니다.

  1. "develop"를 "develop_old"로 이름을 바꿉니다.
  2. develop_old를 새 분기 "develop_new"에 병합하십시오.
  3. 잘못된 병합 전에 develop_new 브랜치를 마지막 커밋으로 재설정하십시오.
  4. 그 이후로 체리는 각 커밋을 하나씩 선택하여 손으로 갈등을 해결합니다.
  5. develop_old 및 develop_new를 원래 위치로 푸시하십시오.

이 시점에서 develop_new는 향후 몇 주 동안의 작업을 다시 적용하여 모든 변경 사항의 "좋은"복사본을 원합니다. 또한 "역 커밋"은 병합에 대해 이상한 일을 할 것이라고 가정합니다. 특히 다음 몇 주 분량의 작업이이 작업에 기반을두고 있기 때문에 병합에는 우리 원하는 많은 것들이 포함되어 있기 때문에 티.

나는 이것이 다시는 일어나지 않기를 바라고 있지만, 다시 일어나면 더 쉽고 더 나은 방법으로 문제를 해결하고 싶습니다. 해당 병합을 기반으로 저장소에서 많은 작업이 진행된 경우 "나쁜"병합을 실행 취소하는 더 좋은 방법이 있습니까?


1
git log다양한 커밋에서 발생한 일에 대한 적절한 주석 이있는 자식 트리의 스크린 샷 (적절하게 편집 됨) 또는 좋아하는 형식 의 출력을 게시 할 수 있습니까? (I는 편집하다 / 주석 것 git log --graph --pretty=oneline --abbrev-commit거기에서 이동)

1
너무 늦었지만 단위 테스트로 인해 문제가 발생했을 수 있습니다.
nalply

1
@nalply : 잘못된 병합으로 인해 유닛 테스트가 삭제 된 경우에는 해당되지 않습니다.
Aaronaught

와우, 그것은 정말 교활한 불운입니다.
nalply

답변:


6

내가 올바르게 이해하면 이것이 당신의 상황입니다.

    ,-c--c--c--c--M--a--a--X ← develop
o--o--y--y--y--y-´

몇 가지 공통된 역사 (o) 후에, 당신은 당신의 일을 약속하고 추진했습니다 (y). 동료 (c)가 로컬 저장소에서 작업했으며 잘못된 병합 (M)을 수행했습니다. 나중에 M 위에 추가 커밋이있을 수 있습니다 (a).

git reset --hard develop M^2
git branch coworker M^1

이제 그래프는 잘못된 병합 전에 정확하게 보입니다.

    ,-c--c--c--c ← coworker
o--o--y--y--y--y ← develop

잘 병합하십시오 (G) :

git checkout develop
git merge coworker

를 야기하는:

    ,-c--c--c--c-、
o--o--y--y--y--y--G ← develop

이제 추가 커밋을 이식하십시오.

git reset --hard X
git rebase --onto G M develop

최종 결과는 다음과 같습니다.

    ,-c--c--c--c-、
o--o--y--y--y--y--G--a--a--X ← develop

병합 충돌이 발생할 수 있습니다. 또한 기록을 변경했습니다. 즉, 모든 동료가 새로운 기록으로 복제 / 재설정 / 리베이스해야합니다.

PS : 물론 당신은 교체해야의 G, M그리고 X커밋 해당 ID로 당신의 명령에.


이 커밋이 모두 이미 공유 리포지토리로 푸시되었다는 질문에서 분명히 알 수 있으므로 rebasing이 좋은 선택이라고 생각하지 않습니다. 최근의 모든 커밋을 되 돌린 다음 좋은 합병의 상단에서 되 돌린 충돌하지 않는 커밋을 체리 피킹하는 것이 더 안전합니다.
Aaronaught

그것은 클론 / 리셋 / 리베이스의 일부였습니다. -개발자가 적은 경우 리포지토리를 업데이트하도록 알리는 것이 유효한 옵션 일 수 있습니다.
michas

1

리포지토리를 수정하는 방법에 대해 생각하는 것이 좋지만 동료가 새 파일 삭제하고 많은 업데이트를 덮어 쓰지 않은 경우 삭제 된 파일을 간단히 복원하는 것이 훨씬 간단한 방법입니다.

아마도 현재 누락 된 코드를 추가 한 원래 커밋을 체리 픽 (현재 헤드로)하려고 시도했을 것입니다. 어떤 이유로 든 작동하지 않으면 추가 한 파일로 이전 버전을 확인한 후 새 커밋에 다시 추가하십시오.

당신이 묘사 한 것은 실제로 잘 알려진 Git 안티 패턴의 하위 집합입니다. 내 인생에서는 이름을 기억할 수 없지만 그 요지는 Git 병합 중에 "수동 편집"을 수행합니다 (예 : 편집) 실제로 병합 충돌을 해결하지는 않지만 완전히 관련이없는 변경을 만들고 있습니다)는 본질적으로 병합 자체에 의해 가려져 코드 검토 또는 디버깅 세션에서 쉽게 간과되기 때문에 매우 나쁜 습관으로 간주됩니다.

따라서 동료에게 이것이 대단한 실패라고 설명하지만 대수술을 준비하기 전에 반창고를 때리는 것을 고려하십시오.


이전 파일의 히스토리를 신경 쓰지 않으면 전체 파일이 전체 파일 인 경우 동의합니다. 1. 현재 엉망이 된 지점에서 새 지점을 만듭니다. 2. 나쁜 지점으로 다시 전환하고 복구 지점 인 다른 새 지점을 만듭니다. 3. 복구 지점에서 실패 커밋 전에 커밋으로 돌아갑니다. 4. 삭제 된 파일을 git 외부에 복사하십시오. 5. 다른 새 분기로 전환하십시오. 6. 삭제 된 파일의 새 버전을 새 분기로 복사하고 커밋합니다. Linus T의 유명한 포스트 인 역사를 저장하는 더 복잡한 방법이 있습니다.
Elin

1
실제로 이것은 체크 아웃 jasonrudolph.com/blog/2009/02/25 / ...를 사용하는 방법을 보여줍니다 . 훨씬 좋습니다.
Elin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.