Re: [PATCH v3 15/15] rebase: change the default backend from "am" to "merge"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jan 16, 2020 at 12:35 PM Jonathan Nieder <jrnieder@xxxxxxxxx> wrote:
>
> > Of course, arguing against myself, we could always tell them to just
> > implement a post-rewrite hook.
>
> That's an interesting facet I hadn't thought about before.
>
> It's tempting since it kind of minimizes the blast surface while
> providing people a way to keep doing what they had wanted.
>
> Historically "git cherry-pick" ran "git commit", causing it to run the

What do you mean "historically"?  I'm pretty sure this piece of code
is shared in the sequencer between rebase -i, rebase --merge, and
cherry-pick, so all three currently call post-commit unless I'm
mistaken.

> post-commit hook.  There's some related discussion at
> https://lore.kernel.org/git/20f33df8-7ba8-af26-e0c8-16152345c85b@xxxxxxxxxxxx/
> of other side effects of having run "git commit".
>
> ... oh! git cherry-pick doesn't run post-rewrite.  Interesting.
>
> To summarize what we've discussed so far:
>
>  A. run post-commit hook consistently in rebase --am and --merge modes

Could you spell these out a bit more?  I think by this option you mean
"Always run post-commit when commits are created", which includes
whether those commits were created by git-commit, git-rebase (any
backend), git-merge, git-cherry-pick, git-revert, git-am, etc. (but
with a glaring exception for fast-import and things that call it, much
like the exception post-rewrite already carves out for it).

Much as I don't see a reason to make rebase --merge different than
rebase --am, I don't see a reason to differentiate between git-merge
and git-commit.  I also don't see why rebase --am should be different
than am.

>     Advantages:
>     * consistent with historic "rebase -i" behavior
>     * supports hooks like ctags generation that want to update state to
>       match what has been committed in the worktree (especially when
>       preparing for the rebase to stop due to conflicts)
>     * consistent with other commands like "git cherry-pick" that run the
>       post-commit hook
>
>     Disadvantages:
>     * invokes hooks more often in a setting they are not used to being
>       invoked in
>     * slows down rebase
>     * when post-commit hooks are used for deployment, exposes
>       intermediate states in the middle of a rebase to the deployment
>       environment
>     * inconsistent with "git am"

I don't want to introduce additional inconsistencies.  git-am and git
merge should be changed at the same time if we go this route.

>     Mitigations:
>     * could go through the normal warn about change, opt-in config,
>       opt-out config cycle to make the change smoother
>     * could provide new hooks (e.g., one run after a batch of objects
>       is created for applications similar to "git gc --auto", one run
>       when HEAD is updated for applications like the ctags one, one
>       run on ref update for applications like the deployment case) and
>       encourage authors to migrate to them
>     * could run the post-commit hook in "git am", too



>  B. stop running the post-commit hook in rebase

AND sometimes in both cherry-pick and git-revert, depending on the
number of commit(s) picked/reverted (see below).

Also, even if we go this route, I think the post-commit hook should be
added to git-merge whenever it creates a merge commit.

>     Advantages:
>     * makes --am and --merge consistent with minimal user impact

...and also makes --interactive and --exec and other cases consistent too.

>     Disadvantages:
>     * meaning of the post-commit hook remains a muddle

Why?  "Commands which create no more than one commit (git-commit,
git-merge, maybe single-commit git-revert or git-cherry-pick) call
post-commit, commands which create several commits derived from others
(git-am, git-rebase, git-cherry-pick, sometimes git-revert ) call
post-rewrite instead for performance reasons" (with the standard
exception for fast-import; also, git-merge could probably call
post-rewrite in fast-forward cases since no new commit is created to
call post-commit on).

Or we could just say that commands which can create multiple commits
(cherry-pick & revert) only call post-rewrite even in cases where they
are only called with one commit (since am and rebase can also be
called on just one commit).

>     * in particular, "git am" and "git rebase" would not be consistent
>       with "git cherry-pick"

Yeah, I'd rather not introduce more inconsistencies; we should pick a
rule and enforce it universally.  Thus, I'd say option B would
probably be thought of as the "always creates at most one commit" vs.
"creates multiple commits" split for post-commit vs. post-rewrite.

>     Mitigations:
>     * could provide new hooks for people to migrate to to replace that
>       muddle
>
>  C. stop running the post-commit hook in rebase --merge or commit --amend
>
>     Advantages:
>     * produces a consistent definition of post-commit ("it's about new
>       commits only")

But cherry-pick never creates "new" commits if commit --amend doesn't,
so we'd also want to turn the post-commit hook off for cherry-pick,
right?  And we'd want to turn post-commit on for git-merge, at least
for non-fast-forward cases since those create new commits.

>     * hook authors get the same expressiveness using the post-rewrite hook

Isn't this also an advantage for case B?  Any reason it was left off up there?

>     Disadvantages:
>     * the change to historical "git commit --amend" behavior is likely
>       to be surprising

That is certainly one issue, but I'd say this case is riddled with
problems and is the most muddled of all.  Once you change git commit
--amend behavior because it's about *new* commits only then you've got
a huge can of worms from rebase -i:

For interactive rebases, we have to avoid the post-commit hook for
anything that is a pick, but if they break or edit and insert new
commits then we have to call the post-commit hook for those.  If the
rebase stops due to a merge conflict, then the next commit created
needs to avoid the post-commit hook.  If they pick to squash or fixup
commits, then we have to deploy rename/break detection to determine
whether the commit is "new" or not and thus whether the post-commit
hook should be triggered for it.  Actually, maybe we need the
rename/break-detection logic when the rebase stops at a conflict too
due to user edits.  And then we start getting into questions about
whether the normal heuristics for rename/break-detection apply or if
"new-ness" should have its own set of heuristics...

Also,  I can't tell if a reverted commit count as "new" or not.  Even
if it does, what about the case of a reverted revert, or higher order
iterations of reverts (which I see occasionally)?

Does this definition mean we should use the git-cherry machinery on
any new commits to search for "newness" (maybe even with an extension
to search across all branches) before we decide whether to call the
post-commit hook?

I think case C is opening up a pandora's box of craziness.

>     Mitigations:
>     * could go through the warn, opt-in config, opt-out config cycle
>
> Any bits I've missed?
>
> Thanks,
> Jonathan


I think it was useful to phrase it this way and list the various
advantages, disadvantages, and mitigations; thanks.

Is there anything I've missed in my additional details?  Anything
sound crazy (beyond what I said I think case C leads to)?


Elijah



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux