简体   繁体   中英

Git save changes in a 'recovery point' without committing and continue in the same branch?

I'm working in a new feature and I have made changes in my branch without commiting them because the code is not complete/stable. But then I realise that maybe I can do some refactor to improve a part of the code I have changed, but I'm not sure if the refactor is going to work properly. So I want to save my changes temporally and continue editing the files in the current state. And if the refactorization goes well, everything fine, I can continue coding and when finished all the code, make a commit. But if the refactor doesn't works I want to revert my refactorization changes until the recovery point (but preserving the changes I have made so far).

I don't want to make a git stash because I dont want to undo all my changes, I want to keep working on my changes, and modify only a few lines of that changes. The only way I know until now is to make a commit with a name something like "fake commit to try a refactor", but I think is not the proper way of doing that.

The Git stage is actually a good option for your use case. You may git add all your changed files which you would want to appear in the commit (were to commit right now). Then, just keep working on your test refactor. This would only affect the files in the working directory, but not the stage.

If you decide to keep the changes from your test refactor, then just do another round of git add to any files you have changed. If you decide to discard the changes to the working directory, then use git checkout -- to reset those files.

Your use case is one reason why the Git stage exists.

The simplest is to use stash.... but not one command but two:

git stash save "blah blah"
git stash apply # get the changes back, keep them on the stash as well

This is specifically what commits are for. You can always undo a commit as long as you haven't pushed it to a remote.

Create a new commit [1] for your checkpoint, then amend [2] the checkpoint commit if you decide to keep your refactoring work. If you need to go back to your checkpoint, you can reset [3] to undo the refactoring.

# [1] Create a checkpoint commit
git commit -A -m checkpoint

# Then, make some changes,followed by either:

# [2] amend the previous checkpoint with your new changes:
git commit -A --amend

# or

# [3] undo everything since the last checkpoint:
git reset --hard HEAD

IMPORTANT UPDATE - As I originally wrote this, I gave the wrong options to reset in the event you're undoing the commit because the refactor failed. The command I gave would drop the commit and remove its changes from the index and working tree , which is not what you'll want to do in this scenario. It would be possible to recover, but you probably would want to do it the way it's written now.


I can think of three solutions that are reasonable.

The first - the one I would do - is to commit. A commit that isn't pushed doesn't have to be permanent. So now you would

git commit

If the refactor fails, you would discard your changes (restoring to the committed state) and then discard the commit

git reset HEAD -- :/:
git checkout -- :/:
git reset --soft HEAD^

But if the refactor doesn't fail, you can amend the commit

git commit --amend

even if you aren't ready to commit right after the refactor, you could keep working and then later amend the commit.

For that matter, even if you made multiple WIP commits, you could still get rid of them when your'e done using interactive rebase. (See the git rebase docs for details; you'd want to "squash" the commits rather than delete them, because the terminology used by rebase is a bit 'off".)

That is by far the safest solution - meaning, least likely to make a mistake and lose work. But if you really don't want to do that, you could use stashes (stash, then apply the stash, then if you have to revert you go back the previous commit and apply the stash again), or just use the index (but if you make any mistakes using eg add or reset, you can lose your save point).

You can use git commit as often as possible. When the code is fine enough, you can refactor the commits to create a nice and clean history.

Suppose you've created 5 new draft commits on the feature branch since the commit O. The history is OABCDE . Now the code is perfect. You can convert the 5 new commits to a single one:

git reset O --soft
git commit -m'perfect commit'

The history now becomes ON . If you find something still needs modifying, you can just modify and use git commit --amend to make N more perfect.

You might find N contains too many changes and it's better to split it into 3 commits.

# --mixed can be omitted as it's the default option
git reset O --mixed

# if you want to split changes of one file to different commits, use -p to selectively add the changes 
git add -p foo1.txt
git commit -m'1st perfect commit'

git add foo2.txt
git commit -m'2nd perfect commit'

# add the rest changes
git add .
git commit -m'3rd perfect commit'

And now the history is O-P1-P2-P3 .

The only way I know until now is to make a commit with a name something like "fake commit to try a refactor", but I think is not the proper way of doing that

I think it is a proper way of doing that. Commits you haven't pushed are local commits, they're the notes on your desk, first-draft work being readied for publication, subject to rewrites as you organize and clarify your work for presentation.

There is nothing sacred about a commit. Commits other people are relying on, that's a different matter, and before dvcs's were invented there couldn't be any distinction between the two, between pu[bli]shed and unpublished, you simply could not have local commits because every vcs lacked the facility, so the language and customs that evolved around them lacked even the concept.

Work you haven't published can be rewritten and reworked until it's good enough to publish. Local commits don't have to be anything more permanent than a beefed-up multi-file extension of your editor's undo buffers, and they're valuable enough when used as exactly that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM