변경 사항을 유지하면서 Git 리포지토리에서 선택된 커밋 로그 항목을 제거하는 방법은 무엇입니까? 다음과 같습니다. R–A–B–C–D–E–HEAD 커밋 로그에 표시되지

항목이 커밋 로그에 표시되지 않도록 선형 커밋 트리에서 선택한 커밋 로그 항목을 제거하고 싶습니다.

내 커밋 트리는 다음과 같습니다.

R--A--B--C--D--E--HEAD

커밋 로그에 표시되지 않도록 B 및 C 항목을 제거하고 싶지만 A에서 D 로의 변경 사항은 유지해야합니다. 아마도 단일 커밋을 도입하여 B와 C가 BC가되고 나무가 보이도록 할 수 있습니다.

R--A--BC--D--E--HEAD

또는 이상적으로 A가 D를 직접 온 후에. A에서 B로, B에서 C로, C에서 D 로의 변화를 나타내는 D ‘.

R--A--D'--E--HEAD

이게 가능해? 그렇다면 어떻게?

이것은 상당히 새로운 프로젝트이므로 현재 지점이 없으므로 병합도 없습니다.



답변

git-rebase (1) 은 정확히 그렇게합니다.

$ git rebase -i HEAD~5

git awsome-ness [git rebase –interactive] 는 예제를 포함합니다.

  1. git-rebase공개 (원격) 커밋에 사용하지 마십시오 .
  2. 작업 디렉토리가 깨끗해야합니다 ( commit또는 stash현재 변경 사항).
  3. 위 명령을 실행하십시오. 시작합니다 $EDITOR.
  4. pick이전 CD로 교체하십시오 squash. 커밋을 삭제하려면 해당 라인을 삭제하면됩니다.

길을 잃은 경우 다음을 입력하십시오.

$ git rebase --abort


답변

# detach head and move to D commit
git checkout <SHA1-for-D>

# move HEAD to A, but leave the index and working tree as for D
git reset --soft <SHA1-for-A>

# Redo the D commit re-using the commit message, but now on top of A
git commit -C <SHA1-for-D>

# Re-apply everything from the old D onwards onto this new place
git rebase --onto HEAD <SHA1-for-D> master


답변

제거하려는 커밋 ID 만 알고 특정 커밋 ID를 제거하는 방법은 다음과 같습니다.

git rebase --onto commit-id^ commit-id

이렇게하면 커밋에 의해 도입 된 변경 사항이 실제로 제거됩니다.


답변

JF Sebastian의 답변을 확장하려면 :

git-rebase를 사용하면 커밋 히스토리를 쉽게 변경할 수 있습니다.

git rebase –interactive를 실행하면 $ EDITOR에 다음이 표시됩니다.

pick 366eca1 This has a huge file
pick d975b30 delete foo
pick 121802a delete bar
# Rebase 57d0b28..121802a onto 57d0b28
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit

행을 이동하여 커밋 순서를 변경하고 행을 삭제하여 해당 커밋을 제거 할 수 있습니다. 또는 두 커밋을 단일 커밋 (이전 커밋은 위의 커밋), 커밋 편집 (변경된 내용) 또는 커밋 메시지 변경에 대한 명령을 추가 할 수 있습니다.

선택은 단지 그 커밋을 내버려두고 싶다는 것을 의미한다고 생각합니다.

(예는 여기에서 )


답변

다음 을 사용하여 예제에서 B와 C를 비 대화식으로 제거 할 수 있습니다 .

git rebase --onto HEAD~5 HEAD~3 HEAD

또는 상징적으로

git rebase --onto A C HEAD

B와 C의 변경 사항 은 D에 있지 않습니다 . 그들은 사라질 것이다.


답변

한 가지 더

git rebase -i ad0389efc1a79b1f9c4dd6061dca6edc1d5bb78a (C's hash)
and
git push origin master  -f

기본으로 사용하려는 해시를 선택하면 위의 명령은 대화식으로 만들어야 모든 최상위 메시지를 스쿼시 할 수 있습니다 (가장 오래된 것을 남겨 두어야 함)


답변

A의 SHA1에서 다른 브랜치를 만들고 원하는 변경 사항을 체리 피킹 하여이 프로세스가 훨씬 안전하고 이해하기 쉽다는 것을 알았습니다. 그런 다음 이전 분기를 쉽게 제거하고 새 분기의 이름을 쉽게 바꿀 수 있습니다.

git checkout <SHA1 of A>
git log #verify looks good
git checkout -b rework
git cherry-pick <SHA1 of D>
....
git log #verify looks good
git branch -D <oldbranch>
git branch -m rework <oldbranch>