etc./StackOverFlow

Git을 사용하여 가장 최근 커밋을 새 브랜치로 이동

청렴결백한 만능 재주꾼 2021. 9. 23. 22:51
반응형

질문자 :Mark A. Nicolosi


마스터하기로 커밋한 마지막 몇 개의 커밋을 새 분기로 옮기고 해당 커밋이 수행되기 전으로 마스터를 되돌리고 싶습니다. 불행히도 내 Git-fu가 아직 충분히 강력하지 않습니다. 도움이 필요하십니까?

즉 내가 어떻게 갈 수 있습니까?

 master A - B - C - D - E

이에?

 newbranch C - D - E / master A - B


답변자 : Community Wiki


기존 지점으로 이동

커밋을 기존 분기 로 이동하려면 다음과 같이 표시됩니다.

 git checkout existingbranch git merge master git checkout master git reset --hard HEAD~3 # Go back 3 commits. You *will* lose uncommitted work. git checkout existingbranch

git stash 사용하여 이 작업을 수행하기 전에 커밋되지 않은 편집 내용을 stash에 저장할 수 있습니다. git stash pop 사용하여 숨겨진 커밋되지 않은 편집을 검색할 수 있습니다.

새 지점으로 이동

경고: git branch newbranch 로 새 분기를 생성하기 때문에 작동합니다. 커밋을 기존 분기 로 이동하려면 git reset --hard HEAD~3 실행하기 전에 변경 사항을 기존 분기로 병합해야 합니다( 위의 기존 분기로 이동 참조). 변경 사항을 먼저 병합하지 않으면 손실됩니다.

관련된 다른 상황이 없는 한 분기 및 롤백을 통해 쉽게 수행할 수 있습니다.

 # Note: Any changes not committed will be lost. git branch newbranch # Create a new branch, saving the desired commits git reset --hard HEAD~3 # Move master back by 3 commits (Make sure you know how many commits you need to go back) git checkout newbranch # Go to the new branch that still has the desired commits

그러나 얼마나 많은 커밋을 되돌릴 것인지 확인하십시오. 또는 HEAD~3 대신 마스터 (/current) 분기에서 "되돌리기"하려는 커밋(또는 origin/master 같은 참조)의 해시를 제공하면 됩니다. 예:

 git reset --hard a1b2c3d4

*1 master 브랜치의 커밋만 "잃어버릴" 것이지만 걱정하지 마세요. 해당 커밋은 newbranch에 있을 것입니다!

경고: Git 버전 2.0 이상을 사용하면 나중에 master ) 분기에 새 분기를 git rebase 하는 경우 이월된 커밋을 잃지 않기 위해 rebase 중에 --no-fork-point 옵션이 필요할 수 있습니다. branch.autosetuprebase always 설정하면 이 가능성이 높아집니다. 자세한 내용은 John Mellor의 답변 을 참조하십시오.



답변자 : Ryan Lundy


그것이 작동하는 이유를 궁금해하는 사람들을 위해(처음처럼):

C로 돌아가서 D와 E를 새 분기로 이동하려고 합니다. 처음에는 다음과 같습니다.

 ABCDE (HEAD) ↑ master

git branch newBranch 이후:

 newBranch ↓ ABCDE (HEAD) ↑ master

git reset --hard HEAD~2 :

 newBranch ↓ ABCDE (HEAD) ↑ master

분기는 포인터일 뿐이므로 마스터 는 마지막 커밋을 가리켰습니다. newBranch 를 만들 때 마지막 커밋에 대한 새 포인터를 만들었습니다. 그런 다음 git reset 을 사용하여 마스터 포인터를 두 커밋 뒤로 옮겼습니다. 그러나 newBranch를 이동하지 않았기 때문에 원래 수행했던 커밋을 여전히 가리킵니다.



답변자 : Ivan


일반적으로...

이 경우에는 sykora에 의해 노출되는 방법이 최선의 선택입니다. 그러나 때로는 가장 쉬운 방법이 아니며 일반적인 방법이 아닙니다. 일반적인 방법의 경우 git cherry-pick를 사용하십시오 .

OP가 원하는 것을 달성하기 위해 2단계 프로세스:

newbranch 원하는 마스터의 커밋 기록

실행하다

 git checkout master git log

newbranch 원하는 커밋(예: 3)의 해시를 확인하세요. 여기에서 나는 다음을 사용할 것이다:
C 커밋: 9aa1233
D 커밋: 453ac3d
전자 커밋: 612ecb3

참고: 처음 7자 또는 전체 커밋 해시를 사용할 수 있습니다.

2단계 - newbranch

 git checkout newbranch git cherry-pick 612ecb3 git cherry-pick 453ac3d git cherry-pick 9aa1233

또는 (Git 1.7.2 이상에서는 범위 사용)

 git checkout newbranch git cherry-pick 612ecb3~1..9aa1233

git cherry-pick은 이 세 가지 커밋을 newbranch에 적용합니다.



답변자 : John Mellor


대부분의 이전 답변은 위험할 정도로 잘못되었습니다!

다음과 같이 하지 마십시오.

 git branch -t newbranch git reset --hard HEAD~3 git checkout newbranch

git rebase (또는 git pull --rebase )를 실행할 때 newbranch 에서 자동으로 삭제됩니다! (아래 설명 참조)

대신 다음을 수행하십시오.

 git reset --keep HEAD~3 git checkout -t -b newbranch git cherry-pick ..HEAD@{2}
  • 먼저 가장 최근의 커밋 3개를 버립니다( --keep--hard 와 비슷하지만 커밋되지 않은 변경 사항을 버리는 것보다 실패하므로 더 안전합니다).
  • 그런 다음 newbranch 분기합니다.
  • 그런 다음 3개의 커밋을 newbranch 다시 선택합니다. 더 이상 브랜치에서 참조하지 않기 때문에 git의 reflog 를 사용하여 이를 수행합니다. HEAD@{2} HEAD 가 2개 작업 전에 참조하는 데 사용한 커밋입니다 newbranch 및 2. used git reset 3개의 커밋을 삭제하도록 git reset

경고: reflog는 기본적으로 활성화되어 있지만 수동으로 비활성화한 경우(예: "bare" git 저장소를 사용하여) git reset --keep HEAD~3 .

reflog에 의존하지 않는 대안은 다음과 같습니다.

 # newbranch will omit the 3 most recent commits. git checkout -b newbranch HEAD~3 git branch --set-upstream-to=oldbranch # Cherry-picks the extra commits from oldbranch. git cherry-pick ..oldbranch # Discards the 3 most recent commits from oldbranch. git branch --force oldbranch oldbranch~3

(원하는 경우 @{-1} - 이전에 체크아웃한 분기 - oldbranch ).


기술적 설명

git rebase 가 첫 번째 예제 이후에 3개의 커밋을 버리는 이유는 무엇입니까? 인수가 없는 git rebase --fork-point 옵션은 로컬 reflog를 사용하여 강제로 푸시되는 업스트림 분기에 대해 강건해지려고 합니다.

M1, M2, M3 커밋이 포함되어 있을 때 origin/master에서 분기한 다음 직접 세 번 커밋했다고 가정합니다.

 M1--M2--M3 <-- origin/master \ T1--T2--T3 <-- topic

그러나 누군가 M2를 제거하기 위해 Origin/master를 강제로 푸시하여 기록을 다시 작성합니다.

 M1--M3' <-- origin/master \ M2--M3--T1--T2--T3 <-- topic

로컬 reflog를 사용하여 git rebase 는 원본/마스터 브랜치의 이전 구현에서 분기되어 M2 및 M3 커밋이 실제로 토픽 브랜치의 일부가 아님을 확인할 수 있습니다. 따라서 M2가 업스트림 분기에서 제거되었으므로 주제 분기가 다시 기반으로 지정되면 더 이상 주제 분기에서 M2를 원하지 않는다고 합리적으로 가정합니다.

 M1--M3' <-- origin/master \ T1'--T2'--T3' <-- topic (rebased)

이 동작은 이해가 되며 일반적으로 리베이스할 때 올바른 방법입니다.

따라서 다음 명령이 실패하는 이유:

 git branch -t newbranch git reset --hard HEAD~3 git checkout newbranch

reflog를 잘못된 상태로 두기 때문입니다. Git은 newbranch 가 3개의 커밋을 포함하는 개정판에서 업스트림 분기를 분기한 reset --hard 가 커밋을 제거하기 위해 업스트림의 기록을 다시 작성하므로 다음에 git rebase 를 실행할 때 다른 커밋처럼 삭제합니다. 업스트림에서 제거되었습니다.

그러나 이 특별한 경우에 우리는 그 3개의 커밋이 토픽 브랜치의 일부로 고려되기를 원합니다. 이를 달성하려면 3개의 커밋을 포함하지 않는 이전 개정판에서 업스트림을 분기해야 합니다. 이것이 내가 제안한 솔루션이 수행하는 작업이므로 둘 다 reflog를 올바른 상태로 둡니다.

자세한 내용은 git rebasegit merge-base 문서 --fork-point 정의를 참조하세요.



답변자 : aragaer


이 작업을 수행하는 또 다른 방법은 단 2개의 명령을 사용하는 것입니다. 또한 현재 작업 트리를 그대로 유지합니다.

 git checkout -b newbranch # switch to a new branch git branch -f master HEAD~3 # make master point to some older commit

이전 버전 git branch -f 대해 배우기 전

 git checkout -b newbranch # switch to a new branch git push . +HEAD~3:master # make master point to some older commit

push 할 수 . 알아두면 좋은 트릭입니다.



답변자 : Slam


git stash를 사용하는 훨씬 간단한 솔루션

다음은 잘못된 분기에 대한 커밋에 대한 훨씬 간단한 솔루션입니다. 세 번의 잘못된 커밋이 있는 master 에서 시작:

 git reset HEAD~3 git stash git checkout newbranch git stash pop

이것을 언제 사용합니까?

  • 주요 목적이 master
  • 파일 변경 사항을 유지하려는 경우
  • 잘못된 커밋에 대한 메시지는 신경 쓰지 않습니다.
  • 당신은 아직 밀지 않았다
  • 당신은 이것을 암기하기 쉽길 원합니다
  • 임시/새 분기, 커밋 해시 찾기 및 복사, 기타 골치 아픈 문제와 같은 복잡한 문제를 원하지 않습니다.

이것이 하는 일, 줄 번호로

  1. master 대한 마지막 세 커밋(및 해당 메시지)을 취소하지만 모든 작업 파일은 그대로 둡니다.
  2. 모든 작업 파일 변경 사항을 숨겨서 master 작업 트리를 HEAD~3 상태와 정확히 동일하게 만듭니다.
  3. 기존 브랜치로 newbranch
  4. 숨김 변경 사항을 작업 디렉토리에 적용하고 숨김을 지웁니다.

이제 평소처럼 git addgit commit 을 사용할 수 있습니다. 모든 새 커밋은 newbranch 추가됩니다.

이것이 하지 않는 일

  • 그것은 당신의 나무를 어지럽히는 임의의 임시 가지를 남기지 않습니다.
  • 잘못된 커밋 메시지를 보존하지 않으므로 이 새 커밋에 새 커밋 메시지를 추가해야 합니다.
  • 업데이트! 위쪽 화살표를 사용하여 명령 버퍼를 스크롤하여 커밋 메시지와 함께 이전 커밋을 다시 적용합니다(@ARK 덕분에).

목표

OP는 목표가 변경 사항을 잃지 않고 "해당 커밋이 수행되기 전으로 마스터를 되돌리는 것"이라고 밝혔으며 이 솔루션이 이를 수행합니다.

develop 대신 master 새로운 커밋을 만들 때 적어도 일주일에 한 번 이 작업을 수행합니다. 일반적으로 롤백할 커밋은 하나만 있는데 git reset HEAD^ 를 사용하는 것이 커밋 하나만 롤백하는 더 간단한 방법입니다.

마스터의 변경 사항을 업스트림으로 푸시한 경우에는 이 작업을 수행하지 마십시오.

다른 사람이 이러한 변경 사항을 가져왔을 수 있습니다. 로컬 마스터만 다시 작성하는 경우 업스트림으로 푸시할 때 영향이 없지만 다시 작성된 기록을 공동 작업자에게 푸시하면 골치 아픈 문제가 발생할 수 있습니다.



답변자 : Sukima


이것은 기술적 의미에서 "이동"하지 않지만 동일한 효과가 있습니다.

 A--B--C (branch-foo) \ ^-- I wanted them here! \ D--E--F--G (branch-bar) ^--^--^-- Opps wrong branch! While on branch-bar: $ git reset --hard D # remember the SHAs for E, F, G (or E and G for a range) A--B--C (branch-foo) \ \ D-(E--F--G) detached ^-- (branch-bar) Switch to branch-foo $ git cherry-pick E..G A--B--C--E'--F'--G' (branch-foo) \ E--F--G detached (This can be ignored) \ / D--H--I (branch-bar) Now you won't need to worry about the detached branch because it is basically like they are in the trash can waiting for the day it gets garbage collected. Eventually some time in the far future it will look like: A--B--C--E'--F'--G'--L--M--N--... (branch-foo) \ \ D--H--I--J--K--.... (branch-bar)


답변자 : teh_senaus


기록을 다시 작성하지 않고 이를 수행하려면(즉, 이미 커밋을 푸시한 경우):

 git checkout master git revert <commitID(s)> git checkout -b new-branch git cherry-pick <commitID(s)>

그러면 두 가지 모두 힘 없이 밀 수 있습니다!



답변자 : Saikat


가장 간단한 방법:

1. 이름 바꾸기 master 당신에 지점 newbranch (당신은에있는 가정 master 지점)

 git branch -m newbranch

2. 원하는 커밋에서 master 브랜치를 생성합니다.

 git checkout -b master <seven_char_commit_id>

예: git checkout -b master a34bc22



답변자 : Darkglow


이 상황이 있었다:

 Branch one: ABCDEFJLM \ (Merge) Branch two: GIKN

나는 수행 :

 git branch newbranch git reset --hard HEAD~8 git checkout newbranch

커밋이 내가 HEAD가 될 것이라고 예상했지만 커밋 L이 지금입니다 ...

기록의 올바른 위치에 착륙하려면 커밋의 해시로 작업하는 것이 더 쉽습니다.

 git branch newbranch git reset --hard ######### git checkout newbranch


답변자 : Ivan


이거에서 어떻게 갈 수 있어?

 A - B - C - D - E | master

이에?

 A - B - C - D - E | | master newbranch

두 가지 명령으로

  • 자식 분기 -m 마스터 새 분기

기부

 A - B - C - D - E | newbranch

그리고

  • 자식 브랜치 마스터 B

기부

 A - B - C - D - E | | master newbranch


답변자 : Shamsul Arefin Sajib


푸시되지 않은 모든 커밋을 새 분기 로 이동해야 하는 경우 다음을 수행하면 됩니다.

  1. 현재 브랜치에서 새 브랜치 생성 git branch new-branch-name

  2. 새 분기를 밀어 : git push origin new-branch-name

  3. 지난 밀어 / 안정된 상태로 이전 (현재) 브랜치를 되돌릴 : git reset --hard origin/old-branch-name

어떤 사람들은 origin upstreams 가지고 있기 때문에 upstream 을 사용해야 합니다.



답변자 : pankaj


내가 사용한 간단한 3단계만 수행하면 됩니다.

1) 최근 업데이트를 커밋하려는 새 분기를 만듭니다.

git branch <branch name>

2) 새 브랜치에 대한 커밋에 대한 최근 커밋 ID를 찾습니다.

git log

3) 가장 최근의 커밋 목록이 맨 위에 있다는 커밋 ID를 복사합니다. 커밋을 찾을 수 있습니다. 당신은 또한 메시지를 통해 이것을 찾을 수 있습니다.

git cherry-pick d34bcef232f6c...

커밋 ID 범위를 제공할 수도 있습니다.

git cherry-pick d34bcef...86d2aec

이제 작업이 완료되었습니다. 올바른 ID와 올바른 분기를 선택했다면 성공할 것입니다. 그래서 이것을하기 전에 조심하십시오. 그렇지 않으면 다른 문제가 발생할 수 있습니다.

이제 코드를 푸시할 수 있습니다.

git push



답변자 : rashok


1) 모든 변경 사항을 new_branch로 이동하는 새 분기를 만듭니다.

 git checkout -b new_branch

2) 그런 다음 이전 분기로 돌아갑니다.

 git checkout master

3) git rebase 실행

 git rebase -i <short-hash-of-B-commit>

4) 그런 다음 열린 편집기에는 마지막 3개의 커밋 정보가 포함됩니다.

 ... pick <C's hash> C pick <D's hash> D pick <E's hash> E ...

5) 3개의 모든 커밋에서 pickdrop 그런 다음 편집기를 저장하고 닫습니다.

 ... drop <C's hash> C drop <D's hash> D drop <E's hash> E ...

6) 이제 마지막 3개의 커밋이 현재 분기( master )에서 제거됩니다. 이제 브랜치 이름 앞에 + 기호를 사용하여 브랜치를 강제로 푸시합니다.

 git push origin +master


답변자 : Quesofat


여기에 있는 대부분의 솔루션은 되돌리려는 커밋의 양을 계산합니다. 나는 이것이 오류가 발생하기 쉬운 방법론이라고 생각한다. 계산에는 다시 계산이 필요합니다.

HEAD에 있고 싶은 커밋의 커밋 해시를 전달하거나 다음을 통해 마지막 커밋이 되고 싶은 커밋을 전달할 수 있습니다.

(커밋 해시 참조)

이것을 피하려면:

 1) git checkout master 2) git branch <feature branch> master 3) git reset --hard <commit hash> 4) git push -f origin master


출처 : Here


출처 : http:www.stackoverflow.com/questions/1628563/move-the-most-recent-commits-to-a-new-branch-with-git">

반응형