Without creating a branch and doing a bunch of funky work on a new branch, is it possible to break a single commit into a few different commits after it's been committed to the local repository?
相关问题
- Why does recursive submodule update from github fa
- Extended message for commit via Visual Studio Code
- Emacs shell: save commit message
- Can I organize Git submodules in a flat hierarchy?
- Upload file > 25 MB on Github
相关文章
- 请教Git如何克隆本地库?
- GitHub:Enterprise post-receive hook
- Git Clone Fails: Server Certificate Verification F
- SSIS solution on GIT?
- Is there a version control system abstraction for
- ssh: Could not resolve hostname git: Name or servi
- Cannot commit changes with gitextensions
- git: retry if http request failed
If you have this:
Where you have committed some content in commit B:
But you want to split B into C - D, and get this result:
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:
Create first commit (C):
Create second commit (D):
Previous answers have covered the use of
git rebase -i
to edit the commit that you want to split, and committing it in parts.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 foredit
, 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
andedit
ing the commit, useto 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 lineThat'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: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 ofgit checkout
which takes both a commit and a file location. Here I use.
as the file location to replace the whole working copy: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:
Finally, once you've committed all the changes,
will carry on and complete the rebase operation.
You can do interactive rebase
git rebase -i
. Man page has exactly what you want:http://git-scm.com/docs/git-rebase#_splitting_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=3EzOz7e1ADIgit 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: