이전 커밋을 여러 커밋으로 나누기
브랜치를 생성하고 새 브랜치에서 여러 가지 펑키 한 작업을하지 않고 로컬 저장소에 커밋 된 후 단일 커밋을 몇 개의 다른 커밋으로 나눌 수 있습니까?
git rebase -i
할 것입니다.
먼저 깨끗한 작업 디렉토리로 시작하십시오. git status
보류중인 수정, 삭제 또는 추가가 표시되지 않아야합니다.
이제 분할 할 커밋을 결정해야합니다.
A) 가장 최근 커밋 분할
가장 최근 커밋을 분리하려면 먼저 다음을 수행하십시오.
$ git reset HEAD~
이제 일반적인 방법으로 조각을 개별적으로 커밋하여 필요한만큼 커밋을 생성합니다.
B) 커밋을 더 뒤로 나누기
이를 위해서는 리베이스 , 즉 히스토리를 다시 작성 해야합니다 . 올바른 커밋을 찾으려면 몇 가지 선택 사항이 있습니다.
세 번의 커밋이면
$ git rebase -i HEAD~3
3
얼마나 많은 커밋이 있는지는 어디에 있습니까 ?세고 싶은 것보다 나무에서 더 멀었다면
$ git rebase -i 123abcd~
123abcd
분할하려는 커밋의 SHA1은 어디에 있습니까 ?마스터로 병합하려는 다른 브랜치 (예 : 기능 브랜치)에있는 경우 :
$ git rebase -i master
rebase 편집 화면이 나타나면 분리 할 커밋을 찾습니다. 그 라인의 시작 부분에서, 교체 pick
로 edit
( e
짧은). 버퍼를 저장하고 종료하십시오. Rebase는 이제 편집하려는 커밋 직후에 중지됩니다. 그때:
$ git reset HEAD~
일반적인 방법으로 조각을 개별적으로 커밋하고 필요한만큼 커밋을 생성 한 다음
$ git rebase --continue
에서 자식-REBASE의 매뉴얼 (분할 섹션 커밋)
대화 형 모드에서는 "edit"작업으로 커밋을 표시 할 수 있습니다. 그러나 이것이 반드시 git rebase가이 편집 결과가 정확히 하나의 커밋이 될 것으로 예상한다는 것을 의미하지는 않습니다. 실제로 커밋을 실행 취소하거나 다른 커밋을 추가 할 수 있습니다. 커밋을 두 개로 분할하는 데 사용할 수 있습니다.
와 상호 작용하는 REBASE 시작
git rebase -i <commit>^
,<commit>
당신이 분할 할 커밋됩니다. 실제로 해당 커밋을 포함하는 한 모든 커밋 범위가 수행됩니다.분할하려는 커밋을 "edit"작업으로 표시합니다.
해당 커밋을 편집 할 때
git reset HEAD^
. 그 효과는 HEAD가 하나씩 되감기 고 인덱스가 그에 따른다는 것입니다. 그러나 작업 트리는 동일하게 유지됩니다.이제 첫 번째 커밋에 포함하려는 인덱스에 변경 사항을 추가하십시오. 이를 위해
git add
(아마도 대화식으로) 또는git gui
(또는 둘 다) 사용할 수 있습니다 .현재 적절한 커밋 메시지로 현재 인덱스를 커밋합니다.
작업 트리가 깨끗해질 때까지 마지막 두 단계를 반복하십시오.
로 리베이스를 계속하십시오
git rebase --continue
.
사용 git rebase --interactive
이전 커밋 실행 편집에 git reset HEAD~
다음, 그리고 git add -p
다음 몇 가지 더 추가 한 다음 커밋 할 몇 가지를 추가하고 다른 당신 같은 수만큼, 커밋 확인합니다. 완료되면을 실행 git rebase --continue
하면 스택의 초기에 모든 분할 커밋이 생성됩니다.
중요 : 당신은 항상 실행할 수 있기 때문에 당신은 오래된 변경을 잃어 버릴까 걱정에 놀러와 당신이 원하는 모든 변경 사항을 확인하지있을 수 있습니다 git reflog
원하는 변경 사항이 포함되어 프로젝트의 지점을 찾기 위해, (현실을 부르 자 a8c4ab
) , git reset a8c4ab
.
작동 방식을 보여주는 일련의 명령은 다음과 같습니다.
mkdir git-test; cd git-test; git init
이제 파일 추가 A
vi A
다음 줄을 추가하십시오.
one
git commit -am one
그런 다음 A :
two
git commit -am two
그런 다음 A :
three
git commit -am three
이제 파일 A는 다음과 같습니다.
one
two
three
그리고 우리의 git log
모습은 다음과 같습니다 (글쎄, 나는git log --pretty=oneline --pretty="%h %cn %cr ---- %s"
bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one
두 번째 커밋을 분할하고 싶다고 가정 해 보겠습니다 two
.
git rebase --interactive HEAD~2
다음과 같은 메시지가 나타납니다.
pick 2b613bc two
pick bfb8e46 three
첫 번째 pick
를로 변경하여 e
해당 커밋을 편집하십시오.
git reset HEAD~
git diff
두 번째 커밋을 위해 만든 커밋을 방금 언 스테이징했음을 보여줍니다.
diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
one
+two
변경 사항을 준비하고 file의 해당 줄에 "and a third"를 추가합니다 A
.
git add .
이는 일반적으로 git rebase --continue
이전 커밋을 편집하기 위해 커밋 스택으로 돌아 가기를 원하기 때문에 일반적으로 대화 형 리베이스 중에를 실행하는 지점 입니다. 하지만 이번에는 새로운 커밋을 만들고 싶습니다. 그래서 우리는 git commit -am 'two and a third'
. 이제 파일을 편집 A
하고 two and two thirds
.
git add .
git commit -am 'two and two thirds'
git rebase --continue
커밋과 충돌이 three
있으므로 해결해 보겠습니다.
우리는 변할거야
one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three
...에
one
two and a third
two and two thirds
three
git add .; git rebase --continue
이제 우리 git log -p
는 다음과 같이 보입니다.
commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <roseperrone@fake.com>
Date: Sun Jul 7 13:57:00 2013 -0700
three
diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
one
two and a third
two and two thirds
+three
commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <roseperrone@fake.com>
Date: Sun Jul 7 14:07:07 2013 -0700
two and two thirds
diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
one
two and a third
+two and two thirds
commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <roseperrone@fake.com>
Date: Sun Jul 7 14:06:40 2013 -0700
two and a third
diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
one
+two and a third
commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <roseperrone@fake.com>
Date: Sun Jul 7 13:56:40 2013 -0700
one
diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one
이전 답변에서는 git rebase -i
분할하려는 커밋을 편집하고 부분적으로 커밋하는 방법에 대해 설명했습니다.
This works well when splitting the files into different commits, but if you want to break apart changes to the individual files, there's more you need to know.
Having got to the commit you want to split, using rebase -i
and marking it for edit
, you have two options.
After using
git reset HEAD~
, go through the patches individually usinggit add -p
to select the ones you want in each commitEdit the working copy to remove the changes you do not want; commit that interim state; and then pull back the full commit for the next round.
Option 2 is useful if you're splitting a large commit, as it lets you check that the interim versions build and run properly as part of the merge. This proceeds as follows.
After using rebase -i
and edit
ing the commit, use
git reset --soft HEAD~
to undo the commit, but leave the committed files in the index. You can also do a mixed reset by omitting --soft, depending on how close to the final result your initial commit is going to be. The only difference is whether you start with all the changes staged or with them all unstaged.
Now go in and edit the code. You can remove changes, delete added files, and do whatever you want to construct the first commit of the series you're looking for. You can also build it, run it, and confirm that you have a consistent set of source.
Once you're happy, stage/unstage the files as needed (I like to use git gui
for this), and commit the changes through the UI or the command line
git commit
That's the first commit done. Now you want to restore your working copy to the state it had after the commit you are splitting, so that you can take more of the changes for your next commit. To find the sha1 of the commit you're editing, use git status
. In the first few lines of the status you'll see the rebase command that is currently executing, in which you can find the sha1 of your original commit:
$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
pick 4847406 US135756: add debugging to the file download code
e 65dfb6a US135756: write data and download from remote
(see more in file .git/rebase-merge/done)
...
In this case, the commit I'm editing has sha1 65dfb6a
. Knowing that, I can check out the content of that commit over my working directory using the form of git checkout
which takes both a commit and a file location. Here I use .
as the file location to replace the whole working copy:
git checkout 65dfb6a .
Don't miss the dot on the end!
This will check out, and stage, the files as they were after the commit you're editing, but relative to the previous commit you made, so any changes you already committed won't be part of the commit.
You can either go ahead now and commit it as-is to finish the split, or go around again, deleting some parts of the commit before making another interim commit.
If you want to reuse the original commit message for one or more commits, you can use it straight from the rebase's working files:
git commit --file .git/rebase-merge/message
Finally, once you've committed all the changes,
git rebase --continue
will carry on and complete the rebase operation.
git rebase --interactive
can be used to split a commit into smaller commits. The Git docs on rebase have a concise walkthrough of the process - Splitting Commits:
In interactive mode, you can mark commits with the action "edit". However, this does not necessarily mean that
git rebase
expects the result of this edit to be exactly one commit. Indeed, you can undo the commit, or you can add other commits. This can be used to split a commit into two:
Start an interactive rebase with
git rebase -i <commit>^
, where<commit>
is the commit you want to split. In fact, any commit range will do, as long as it contains that commit.Mark the commit you want to split with the action "edit".
When it comes to editing that commit, execute
git reset HEAD^
. The effect is that the HEAD is rewound by one, and the index follows suit. However, the working tree stays the same.Now add the changes to the index that you want to have in the first commit. You can use
git add
(possibly interactively) or git gui (or both) to do that.Commit the now-current index with whatever commit message is appropriate now.
Repeat the last two steps until your working tree is clean.
Continue the rebase with
git rebase --continue
.If you are not absolutely sure that the intermediate revisions are consistent (they compile, pass the testsuite, etc.) you should use
git stash
to stash away the not-yet-committed changes after each commit, test, and amend the commit if fixes are necessary.
You can do interactive rebase git rebase -i
. Man page has exactly what you want:
http://git-scm.com/docs/git-rebase#_splitting_commits
Now in the latest TortoiseGit on Windows you can do it very easily.
Open the rebase dialog, configure it, and do the following steps.
- Right-click the commit you want to split and select "
Edit
" (among pick, squash, delete...). - Click "
Start
" to start rebasing. - Once it arrives to the commit to split, check the "
Edit/Split
" button and click on "Amend
" directly. The commit dialog opens.
- Unselect the files you want to put on a separate commit.
- Edit the commit message, and then click "
commit
". - Until there are files to commit, the commit dialog will open again and again. When there is no more file to commit, it will still ask you if you want to add one more commit.
Very helpful, thanks TortoiseGit !
Please note there's also git reset --soft HEAD^
. It's similar to git reset
(which defaults to --mixed
) but it retains the index contents. So that if you've added/removed files, you have them in the index already.
Turns out to be very useful in case of giant commits.
Easiest thing to do without an interactive rebase is (probably) to make a new branch starting at the commit before the one you want to split, cherry-pick -n the commit, reset, stash, commit the file move, reapply the stash and commit the changes, and then either merge with the former branch or cherry-pick the commits that followed. (Then switch the former branch name to the current head.) (It's probably better to follow MBOs advice and do an interactive rebase.)
I think that the best way i use git rebase -i
. I created a video to show the steps to split a commit: https://www.youtube.com/watch?v=3EzOz7e1ADI
If you have this:
A - B <- mybranch
Where you have committed some content in commit B:
/modules/a/file1
/modules/a/file2
/modules/b/file3
/modules/b/file4
But you want to split B into C - D, and get this result:
A - C - D <-mybranch
You can divide the content like this for example (content from different directories in different commits)...
Reset the branch back to the commit before the one to split:
git checkout mybranch
git reset --hard A
Create first commit (C):
git checkout B /modules/a
git add -u
git commit -m "content of /modules/a"
Create second commit (D):
git checkout B /modules/b
git add -u
git commit -m "content of /modules/b"
It's been more than 8 years, but maybe someone will find it helpful anyway. I was able to do the trick without rebase -i
. The idea is to lead git to the same state it was before you did git commit
:
# first rewind back (mind the dot,
# though it can be any valid path,
# for instance if you want to apply only a subset of the commit)
git reset --hard <previous-commit> .
# apply the changes
git checkout <commit-you-want-to-split>
# we're almost there, but the changes are in the index at the moment,
# hence one more step (exactly as git gently suggests):
# (use "git reset HEAD <file>..." to unstage)
git reset
After this you'll see this shiny Unstaged changes after reset:
and your repo is in a state like you're about to commit all these files. From now on you can easily commit it again like you usually do. Hope it helps.
참고URL : https://stackoverflow.com/questions/6217156/break-a-previous-commit-into-multiple-commits
'development' 카테고리의 다른 글
"python -m SimpleHTTPServer"에 해당하는 Python 3는 무엇입니까? (0) | 2020.09.27 |
---|---|
속성별로 사용자 지정 개체의 ArrayList 정렬 (0) | 2020.09.27 |
div의 콘텐츠를 하단에 정렬하는 방법 (0) | 2020.09.27 |
Ruby on Rails의 nil v. empty v. blank에 대한 간결한 설명 (0) | 2020.09.27 |
React JSX 내부 루프 (0) | 2020.09.27 |