program story

과거에 두 개의 임의 커밋 사이에 커밋을 삽입하는 방법은 무엇입니까?

inputbox 2020. 8. 30. 08:15
반응형

과거에 두 개의 임의 커밋 사이에 커밋을 삽입하는 방법은 무엇입니까?


로컬 전용 브랜치에 다음 커밋 기록이 있다고 가정합니다.

A -- B -- C

A사이에 새 커밋을 어떻게 삽입 B합니까?


OP의 답변보다 훨씬 쉽습니다.

  1. git rebase -i <any earlier commit>. 구성된 텍스트 편집기에 커밋 목록이 표시됩니다.
  2. 다음에 삽입 할 커밋을 찾습니다 (라고 가정 해 보겠습니다 a1b2c3d). 편집기에서 해당 줄에 pick대해 edit.
  3. 텍스트 편집기를 닫아 리베이스를 시작하십시오 (변경 사항 저장). 이렇게하면 방금 커밋 된 것처럼 이전에 선택한 커밋 ( a1b2c3d) 이있는 명령 프롬프트가 표시 됩니다.
  4. 변경하고 git commit( 대부분 것과 달리 수정 하지 마십시오edit ). 이렇게 하면 선택한 커밋 뒤에 새 커밋이 생성 됩니다.
  5. git rebase --continue. 그러면 연속 커밋이 재생되고 새 커밋이 올바른 위치에 삽입됩니다.

이것은 역사를 다시 쓰게 될 것이고, 당기려는 다른 사람을 깨뜨릴 것이라는 점에주의하십시오.


여기 에서 찾을 수있는 답은 매우 간단 합니다 . 지점에 있다고 가정합니다 branch. 다음 단계를 수행하십시오.

  • 새 커밋을 삽입하려는 후 커밋에서 임시 분기를 만듭니다 (이 경우 commit A) :

    git checkout -b temp A
    
  • 변경 사항을 수행하고 커밋하고 커밋을 생성하고 호출합시다 N.

    git commit -a -m "Message"
    

    (또는 git add뒤에 git commit)

  • 새 커밋 이후에 원하는 커밋 (이 경우에는 커밋 BC)을 새 커밋으로 리베이스합니다 .

    git rebase temp branch
    

(아마도 ciekawy에 의해 더 이상 존재하지 않는 주석-p 덕분에 병합을 보존 하기 위해 사용해야 합니다 )

  • 임시 분기를 삭제하십시오.

    git branch -d temp
    

그 후의 역사는 다음과 같습니다.

A -- N -- B -- C

물론 리베이스하는 동안 일부 충돌이 나타날 수 있습니다.

지점이 로컬 전용이 아닌 경우 다시 쓰기 기록이 발생하므로 심각한 문제가 발생할 수 있습니다.


더 쉬운 솔루션 :

  1. 마지막에 새 커밋 D를 만듭니다. 이제 다음을 수행합니다.

    A -- B -- C -- D
    
  2. 그런 다음 다음을 실행하십시오.

    $ git rebase -i hash-of-A
    
  3. Git이 편집기를 열면 다음과 같이 표시됩니다.

    pick 8668d21 B
    pick 650f1fc C
    pick 74096b9 D
    
  4. 이렇게 D를 위로 옮기고 저장하고 종료하세요

    pick 74096b9 D
    pick 8668d21 B
    pick 650f1fc C
    
  5. 이제 다음을 갖게됩니다.

    A -- D -- B -- C
    

Assuming that the commit history is preA -- A -- B -- C, if you want to insert a commit between A and B, the steps are as follows:

  1. git rebase -i hash-of-preA

  2. Git will open your editor. The content may like this:

    pick 8668d21 A
    pick 650f1fc B
    pick 74096b9 C
    

    Change the first pick to edit:

    edit 8668d21 A
    pick 650f1fc B
    pick 74096b9 C
    

    Save and Exit.

  3. Modify your code and then git add . && git commit -m "I"

  4. git rebase --continue

Now your Git commit history is preA -- A -- I -- B -- C


If you encounter a conflict, Git will stop at this commit. You can use git diff to locate conflict markers and resolve them. After resolving all conflicts, you need to use git add <filename> to tell Git that the conflict has been resolved and then rerun git rebase --continue.

If you want to undo the rebase, use git rebase --abort.


Here's a strategy that avoids doing an "edit hack" during the rebase seen in the other answers I've read.

By using git rebase -i you obtain a list of commits since that commit. Just add a "break" at the top of the file, this will cause the rebase to break at that point.

break
pick <B's hash> <B's commit message>
pick <C's hash> <C's commit message>

Once launched, git rebase will now stop at the point of the "break". You can now edit your files and create your commit normally. You can then continue the rebase with git rebase --continue. This may cause conflicts you'll have to fix. If you get lost, don't forget you can always abort using git rebase --abort.

This strategy can be generalised to insert a commit anywhere, just put the "break" at the spot where you want to insert a commit.

After rewriting history, don't forget to git push -f. The usual warnings about other people fetching your branch apply.


Many good answers here already. I just wanted to add a "no rebase" solution, in 4 steps.

One advantage of this solution is that you don't touch your branch until the final step, when you're 100% sure you're OK with the end result, so you have a very handy "pre-confirmation" step allowing for AB testing.


Initial state (I've assumed master for your branch name)

A -- B -- C <<< master <<< HEAD

1) Start by pointing HEAD at the right place

git checkout A

     B -- C <<< master
    /
   A  <<< detached HEAD

(Optionnally here, rather than detaching HEAD, we could have created a temporary branch with git checkout -b temp A, which we would need to delete at the end of the process. Both variants work, do as you prefer since everything else remains the same)


2) Create the new commit D to be inserted

# at this point, make the changes you wanted to insert between A and B, then

git commit -am "Message for commit D"

     B -- C <<< master
    /
   A -- D <<< detached HEAD (or <<< temp <<< HEAD)

3) Then bring copies of the last missing commits B and C (would be same line if there were more commits)

git cherry-pick A..C

# (if any, resolve any potential conflicts between D and these last commits)

     B -- C <<< master
    /
   A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)

( comfortable AB Testing here if needed )

Now is the moment to inspect your code, test anything that needs to be tested, and you can also diff / compare / inspect what you had and what you would get after the operations.


4) Depending on your tests between C and C', either it is OK or it is KO.

(EITHER) 4-OK) Finally, move the ref of master

git branch -f master HEAD

     B -- C <<< (B and C are candidates for garbage collection)
    /
   A -- D -- B' -- C' <<< master

(OR) 4-KO) Just leave master unchanged

If you created a temporary branch, just delete it with git branch -d <name>, but if you went for the detached HEAD route, no action needed at all at this point, the new commits will be eligible for garbage collection just after you reattach HEAD with a git checkout master

In both those cases (OK or KO), at this point just checkout master again to reattach HEAD.

참고URL : https://stackoverflow.com/questions/32315156/how-to-inject-a-commit-between-some-two-arbitrary-commits-in-the-past

반응형