Re: BUG? git stash and immediate git apply results in conflict
- From
Chris Torek <chris.torek@gmail.com>
- Date
- Jun 2, 2022, 12:24 UTC
- Message-ID
- <CAPx1GveKYjEoAnhJLkGOo9Esd5-vhkFkbz2Uwy10j5fxR_W9Bw@mail.gmail.com>
- In-Reply-To
- <CAHHcNodnB8gnaLgxW-vr6PxHh_YjCOAf7CTuot-CJsonb1mdnA@mail.gmail.com>
On Thu, Jun 2, 2022 at 4:31 AM Akos Vandra-Meyer <axos88@gmail.com> wrote:
Show 9 quoted lines
> Hi Chris, > > Thanks for getting back to me on this. > My use case is the following: > > I made a bunch of (loosely related) changes to my code, but I have > been asked to submit them as separate commits, so I need to separate > the changes to dependent files relating to the first and second > feature.
I snipped the rest of this because I *dislike* and *recommend against* the use of `git stash` in the first place. If you want to use it that way, I am sure it is possible, but I recommend doing something else entirely. The rest of this message is all opinion! You seem to be looking for a recommended method, so I'm recommending mine.
Let's say for concreteness that your current branch is named "topic". Here is what I would do (though I might change strategies and use various short-cuts depending on various sub-scenarios; this is meant for illustrating how to do what you want, in a way that provides the most clarity):
git add (files as needed) git commit -m "final version, to be split up" git branch -m not-final-topic
Then:
# create a new topic branch git checkout -b new-topic <start-point>
# get a view of commits git log HEAD..topic
# copy some commits, up until some point git cherry-pick <some of those commits as desired>
# begin splitting a commit: git cherry-pick -n <hash>
# split it up: use a mix of the following:
git reset / git add -p / git reset -p
# as needed here to take part of the commit)# observe what's to be committed git diff --cached git commit # and write a commit message
git add -p ... # as needed again git diff --cached git commit # repeat until satisfied with broken up commit(s)
# make sure final result matches - optional: use the same # hash here as for the `git cherry-pick -n` command git diff HEAD <hash>
# repeat copying whole and partial commits:
git cherry-pick ... # add more whole commits as desired
git cherry-pick -n ... # add commit that is to be split up
# repeat the split-up process# When finally done, ensure that new-topic and not-final-topic # have the same contents. If they do, the split-up was successful. git diff not-final-topic HEAD
Note that there is no longer any branch named "topic" at this point: we have instead "not-final-topic" and "new-topic". We can now rename "new-topic" to "topic" and use `git push -f` or whatever else is appropriate for whatever review system(s) you may be using.
The entire process above can often be done with a single `git rebase -i` command, but that obscures the fundamental nature of what you're really doing. The repeated cherry-pick, reset, add -p, and/or reset -p sequence is what you're really doing: you are taking some set of existing commits, which are *close* to the commits you'd like to have, and rebuilding them to make a new set of commits (with different hash IDs) that represent what you really do want.
In the end, you will have Git *find* your commits by name: the name "topic" will name the last commit in a chain of commits. The names here are up to you, and you can change any name at any time using `git branch -m`. Both Git and any review system you use is going to use the *commits*, with their scary looking hash IDs, but like you they will *find* these commits by starting from a branch name: so by changing the hash ID stored in the branch name, you change the set of commits they (and you) find.
What `git stash` does is make several commits that are not on *any* branch. These commits are a little weird, requiring the use of the `git stash` command to access them. Ordinary commits on ordinary branches are not weird and do not need any special access, so that's what I prefer. But the fact that the stash commits are on *no* branch makes it easy to slide them from one branch to another without having to think about hash IDs; that's one reason some people prefer `git stash`. I'm just not one of those people.
Chris