All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Torek <chris.torek@gmail.com>
To: Akos Vandra-Meyer <axos88@gmail.com>
Cc: Git List <git@vger.kernel.org>
Subject: Re: BUG? git stash and immediate git apply results in conflict
Date: Thu, 2 Jun 2022 05:24:50 -0700	[thread overview]
Message-ID: <CAPx1GveKYjEoAnhJLkGOo9Esd5-vhkFkbz2Uwy10j5fxR_W9Bw@mail.gmail.com> (raw)
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:
> 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

      reply	other threads:[~2022-06-02 12:25 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-01  6:55 BUG? git stash and immediate git apply results in conflict Akos Vandra-Meyer
2022-06-02  6:32 ` Chris Torek
2022-06-02 11:31   ` Akos Vandra-Meyer
2022-06-02 12:24     ` Chris Torek [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAPx1GveKYjEoAnhJLkGOo9Esd5-vhkFkbz2Uwy10j5fxR_W9Bw@mail.gmail.com \
    --to=chris.torek@gmail.com \
    --cc=axos88@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.