Mercurial : 마지막 커밋을 수정하는 방법?


211

git commit --amendMercurial 의 상대 부분 , 즉 작업 복사본이 연결된 커밋을 수정하는 방법을 찾고 있습니다. 나는 임의의 이전 커밋이 아닌 마지막 커밋에만 관심이 있습니다.

이 수정 절차의 요구 사항은 다음과 같습니다.

  • 가능하면 확장이 필요하지 않습니다. 그것은 있어야 기본이 아닌 확장이 필요하지 , 공식 의욕 설치 오지 않는, 즉 확장.

  • 수정하려는 커밋이 현재 지점의 헤드경우 새 헤드를 만들면 안됩니다. 커밋이 헤드가 아닌 경우 새 헤드가 생성 될 수 있습니다.

  • 절차는 어떤 이유로 든 수정이 실패하는 경우 수정 전과 동일한 작업 복사본 및 저장소 상태를 복원하려는 방식 으로 안전 해야합니다 . 다시 말해, 수정 자체가 실패 할 경우 작업 사본 및 저장소 상태를 복원하는 실패 방지 절차가 있어야합니다. 파일 시스템 관련 문제 (예 : 액세스 제한, 쓰기를 위해 파일을 잠글 수 없음)가 아니라 수정 절차 (예 : 충돌)의 본질 인 "실패"를 언급하고 있습니다. )

업데이트 (1) :

  • 프로시 저는 자동화 가능 해야 하므로 사용자 조작없이 GUI 클라이언트가이를 수행 할 수 있습니다.

업데이트 (2) :

  • 작업중인 디렉토리의 파일은 건드리지 않아야합니다 (특정 수정 된 파일에는 파일 시스템 잠금이있을 수 있음). 이는 특히 가능한 접근 방식이 깨끗한 작업 디렉토리를 요구하지 않을 수 있음을 의미합니다.

답변:


289

Mercurial 2.2 릴리스에서는 --amendwith 옵션을 사용 hg commit하여 현재 작업 디렉토리로 마지막 커밋을 업데이트 할 수 있습니다

로부터 명령 줄 참조 :

--amend 플래그는 현재 hg 상태에 의해보고 된 변경 사항이있는 경우 부모의 변경 사항이 포함 된 새 커밋으로 작업 디렉토리의 부모를 수정하는 데 사용할 수 있습니다. 이전 커밋은 .hg / strip-backup의 백업 번들에 저장됩니다 (hg 도움말 번들 및 hg 도움말에서 복원 방법에 대한 번들 해제 참조).

메시지, 사용자 및 날짜는 지정되지 않은 한 수정 된 커밋에서 가져옵니다. 명령 행에 메시지를 지정하지 않으면 수정 된 커밋 메시지와 함께 편집기가 열립니다.

가장 좋은 점은이 메커니즘이 "안전"하다는 것입니다.이 메커니즘은 비교적 새로운 "단계"기능을 사용하여 로컬 리포지토리 외부에서 이미 사용 가능한 기록을 변경하는 업데이트를 방지하기 때문입니다.


2
좋은 대답입니다! 실험적 확장 기능을 사용하면 헤드아닌 커밋 을 안전하게 수정할 수 있습니다 . 이전 커밋은 더 이상 사용되지 않고 숨겨져 표시됩니다. 비 게시 서버를 사용하면 변경 세트를 푸시 한 후에도 안전하게 수행 할 수 있습니다.
Martin Geisler

5
마지막 커밋에서 메시지를 업데이트하려면 : hg commit --amend -m "이것은 나의 새 메시지"
Jay Sheth

52

Mercurial에서 커밋을 편집 할 수있는 3 가지 옵션이 있습니다.

  1. hg strip --keep --rev -1마지막 커밋을 취소하면 다시 할 수 있습니다 ( 자세한 내용 은 이 답변 참조 ).

  2. Mercurial과 함께 제공되는 MQ 확장 사용

  3. Mercurial과 함께 제공되지 않더라도 Histedit 확장 프로그램은 언급 할 가치가 있습니다.

Mercurial 위키 의 편집 히스토리 페이지를 볼 수도 있습니다 .

간단히 말해서 편집 기록은 정말 어렵고 권장되지 않습니다 . 이미 변경 사항을 적용한 경우 다른 모든 클론을 완전히 제어 할 수있는 경우를 제외하고는 수행 할 수있는 작업이 거의 없습니다.

나는 git commit --amend명령에 익숙하지 않지만 AFAIK, Histedit는 가장 가까운 접근법 인 것처럼 보이지만 슬프게도 Mercurial과 함께 제공되지 않습니다. MQ는 사용하기가 정말 복잡하지만 거의 모든 작업을 수행 할 수 있습니다.


1
왜 롤백을 놓쳤는 지 모르겠지만 (거의) 원하는 것을하는 것 같습니다. 유일한 문제는, 원래 커밋에 대해 파일이 제거되고 수정 된 커밋에 대해 파일이 복구 된 경우입니다. 작업 디렉토리)
mstrap

@Marc 나는 당신의 문제를 이해하지는 못하지만 forget 명령을 살펴보면 그것이 당신이 찾고있는 것이라고 생각합니다.
krtek

나는 여기서 "잊어 버릴 것"이 도움이되지 않을 것이라고 생각합니다. 여기에 문제가 더 자세하게 설명되어 있습니다. (1) 개정 2에 있습니다. (2) "파일"을 제거하고 다른 변경 사항이 있습니다. (3) 변경 사항을 커밋하여 개정 3을 만듭니다. (4) 이제 마음을 바꾸고 결정하겠습니다. 커밋에서 "file"을 제거해서는 안되므로 개정 3을 수정하고 싶습니다. 따라서 이제 버전이 바뀐 "file"을 다시 추가하겠습니다 (5) 이제 롤백을 수행합니다. dirstate를 재설정하고 " 파일 "을 제거했습니다. (6) "hg commit"을 다시 수행 할 때 "file"은 더 이상 없어야하지만 제거 된 상태로 유지됩니다. 그에 대한 자동 수정은 어떻게 생겼습니까?
mstrap

1
자동화 된 부분은 알지 못하지만 hg revert myfile삭제를 취소 할 수 있습니다 . 아마도 작업 hg add후에 파일로 다시 추가 할 rollback수도 있습니다.
krtek

3
공개 된 변경 사항의 히스토리 편집은 피해야한다는 데 동의하지만, 로컬 히스토리의 편집은 DVCS의 주요 특징 중 하나입니다. qimport가있는 MQ는 순수 히스토리 편집 AFAICT입니다.
mstrap

38

다음에 해당하는 GUI hg commit --amend:

이것은 TortoiseHG의 GUI에서도 작동합니다 (v2.5를 사용하고 있습니다).

'커밋'보기에 들어가거나 워크 벤치보기에서 '작업 디렉토리'항목을 선택하십시오. '커밋'버튼에는 '현재 개정 수정'이라는 옵션이 있습니다 (버튼을 보려면 드롭 다운 화살표를 클릭하십시오).

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

          ||
          ||
          \/

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

주의 사항 :

이 추가 옵션은 수은 버전이 2.2.0 이상이고 현재 개정판이 공개 버전이 아닌 경우 패치가 아니고 하위가없는 경우에만 활성화됩니다. [...]

버튼을 클릭하면 수정을 '수정'하기 위해 'commit --amend'가 호출됩니다.

THG dev 채널에 대한 자세한 정보


매우 도움이되었습니다. 감사합니다. THG는 커밋 (수정) 메시지를 이전 커밋의 메시지로 기본 설정하기에 충분히 똑똑합니다.
UuDdLrLrSs

7

나는 krtek이 쓴 것을 튜닝하고 있습니다. 더 구체적으로 해결책 1 :

가정 :

  • 하나의 (!) 변경 세트를 커밋했지만 아직 푸시하지 않았습니다.
  • 이 변경 세트를 수정하려고합니다 (예 : 파일 추가, 제거 또는 변경 및 / 또는 커밋 메시지)

해결책:

  • hg rollback마지막 커밋을 취소하는 데 사용
  • 새로운 변경 사항을 적용하여 다시 커밋

롤백은 실제로 마지막 작업을 취소합니다. 작업 방법은 매우 간단합니다. HG의 일반적인 작업은 파일에만 추가됩니다. 여기에는 커밋이 포함됩니다. Mercurial은 마지막 트랜잭션의 파일 길이를 추적하므로 파일을 이전 길이로 다시 잘라서 한 단계를 완전히 취소 할 수 있습니다.


1
튜닝 솔루션 (1)에 감사드립니다. 롤백에 작은 문제가 남아 있습니다 .krtek의 솔루션에 대한 의견을 참조하십시오.
mstrap

8
롤백에서 강조해야 할 한 가지는 사람들을 사로 잡기 때문에 마지막 커밋이 아니라 롤백되는 리포지토리 의 마지막 트랜잭션 이라는 것 입니다. 따라서 다른 항목이 저장소에 쓰면 롤백이 도움이되지 않습니다. 미묘하지만 기억해야 할 중요한 사항입니다. 롤백 창이 닫힌 후에도 MQ와 histedit가 도움이 될 수 있지만 여전히 특정 지점까지만 가능합니다.
Paul S

7

아직 변경 사항을 전파하지 않았다고 가정하면 다음을 수행 할 수 있습니다.

  • .hgrc에 추가하십시오.

    [extensions]
    mq =
    
  • 저장소에서 :

    hg qimport -r0:tip
    hg qpop -a
    

    물론 마지막 하나의 팝 ( hg qpop) 만으로도 수정 0으로 시작하거나 모든 패치를 팝할 필요는 없습니다 (아래 참조).

  • .hg/patches/series파일 의 마지막 항목 또는 원하지 않는 패치를 제거하십시오 . 재주문도 가능합니다.

  • hg qpush -a; hg qfinish -a
  • .diff.hg / patches에 있는 파일 (적용되지 않은 패치)을 제거하십시오 (귀하 의 파일이어야 함).

당신이 경우 싶지 않아 하는 모든 철회 당신의 패치를, 당신은 사용하여 편집 할 수 있습니다 hg qimport -r0:tip, 다음 편집 물건과 사용 (또는 유사) hg qrefresh하여 스택의 맨 위의 패치에 변경 내용을 병합 할 수 있습니다. 읽어보십시오 hg help qrefresh.

편집 .hg/patches/series하면 여러 패치를 제거하거나 순서를 바꿀 수도 있습니다. 마지막 개정판이 99이면를 사용할 수 있습니다 hg qimport -r98:tip; hg qpop; [edit series file]; hg qpush -a; hg qfinish -a.

물론이 절차 는 매우 권장되지 않으며 위험 합니다. 이 작업을 수행하기 전에 모든 것을 백업 하십시오!

참고로 개인 전용 리포지토리에서 수백만 번을 수행했습니다.


또한 mq-extension 사용을 고려했지만 일부 파일이 실패 할 수있는 많은 작업이 필요합니다 (예 : 이진 파일이 관련된 경우). 또한이 절차는 GUI 클라이언트 내에서 사용해야하므로 .hg / patch / series를 편집 할 수 없습니다 (위의 요구 사항을 업데이트했습니다)
mstrap

흠, 이것이 당신을위한 것이 아니라는 것을 유감스럽게 생각합니다. 개인 저장소에서 이것은 실제로 엉덩이를 걷어차 게합니다 (백업으로 이미 repfinger를 파괴했습니다 ^^). 아주 사용하여 로컬 변경을 추진하기 전에 하나에 패치를 결합하는 멋진 hg qfoldBTW,
hochl

MQ를 사용하는 데 +1하지만 선외로 갔다고 생각합니다. 그는 마지막 커밋을 수정하는 것에 대해서만 묻습니다. 또한 그 수입은 합병에 도달하자마자 치열해질 것입니다. 'qimport -r 팁; <물건 편집>; qrefresh -e; qfin -a '는 작업을 수행합니다 (-e 커밋 메시지 편집)
Paul S

사실, 병합은 문제입니다. 나는 보통 하나의 패치 만 팝하고 사용 hg import -r<prev>:tip합니다. 한마디로 subversion과 같이 이전 버전에 대한 바로 가기가 없습니다.
hochl

2

최신 버전의 Mercurial에는 명령 evolve을 제공하는 확장 기능이 포함되어 있습니다 hg amend. 이를 통해 버전 관리에서 사전 수정 내역을 잃지 않고 커밋을 수정할 수 있습니다.

hg 수정 [OPTION] ... [FILE] ...

별칭 : 새로 고침

변경 세트를 업데이트와 결합하여 새 것으로 교체

Commits a new changeset incorporating both the changes to the given files
and all the changes from the current parent changeset into the repository.

See 'hg commit' for details about committing changes.

If you don't specify -m, the parent's message will be reused.

Behind the scenes, Mercurial first commits the update as a regular child
of the current parent. Then it creates a new commit on the parent's
parents with the updated contents. Then it changes the working copy parent
to this new combined changeset. Finally, the old changeset and its update
are hidden from 'hg log' (unless you use --hidden with log).

확장에 대한 자세한 설명은 https://www.mercurial-scm.org/doc/evolution/user-guide.html#example-3-amend-a-changeset-with-evolve 를 참조 하십시오evolve .


동일한 커밋 메시지를 재사용하는 것은 좋은 기능입니다!
mpen

1

원래 질문의 모든 문제를 해결할 수는 없지만 이것은 수은이 이전 커밋을 어떻게 수정할 수 있는지에 대한 사실상의 게시물처럼 보이므로 2 센트 분량의 정보를 추가 할 것입니다.

나처럼 파일을 추가하지 않고 이전 커밋 메시지 (오타 수정 등) 만 수정하려는 경우 작동합니다.

hg commit -X 'glob:**' --amend

포함 또는 제외 패턴 hg commit이 없으면 기본적으로 작업 디렉토리의 모든 파일이 포함됩니다. 패턴 -X 'glob:**'을 적용하면 가능한 모든 파일이 제외되고 커밋 메시지 만 수정할 수 있습니다.

기능적 git commit --amend으로 인덱스 / 스테이지에 파일이없는 경우 와 동일 합니다.


0

다른 솔루션은 uncommit명령을 사용하여 현재 커밋에서 특정 파일을 제외시킬 수 있습니다 .

hg uncommit [file/directory]

이것은 현재 커밋을 유지하고 커밋에서 일부 파일을 선택 취소하려는 경우에 특히 유용합니다 (특히 files/directories삭제 된 경우 유용 ).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.