* git commit --amend safety check? @ 2015-03-11 4:31 Shawn Pearce 2015-03-11 5:11 ` Junio C Hamano 0 siblings, 1 reply; 8+ messages in thread From: Shawn Pearce @ 2015-03-11 4:31 UTC (permalink / raw) To: git We keep seeing reports of Gerrit Code Review users who incorrectly do something like: git clone URL foo cd foo git commit --amend -m "My first change!" -a git push URL HEAD:refs/for/master Step #3 is where they get into trouble. They just amended the published tip commit and pushed it back to the server. That is... lets just say not good. Hg is known to be more user friendly. One way its user friendly is it by default refuses to let you amend a change set that the client has reasonable assertion to believe was already published through a remote repository. For Git that would mean `commit --amend` refusing to amend (by default) if the commit is reachable from a refs/remotes/... tracking branch. Thoughts? ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: git commit --amend safety check? 2015-03-11 4:31 git commit --amend safety check? Shawn Pearce @ 2015-03-11 5:11 ` Junio C Hamano 2015-03-11 6:00 ` Shawn Pearce 2015-03-11 8:37 ` Peter Krefting 0 siblings, 2 replies; 8+ messages in thread From: Junio C Hamano @ 2015-03-11 5:11 UTC (permalink / raw) To: Shawn Pearce; +Cc: git Shawn Pearce <spearce@spearce.org> writes: > We keep seeing reports of Gerrit Code Review users who incorrectly do > something like: > > git clone URL foo > cd foo > git commit --amend -m "My first change!" -a > git push URL HEAD:refs/for/master > > Step #3 is where they get into trouble. They just amended the > published tip commit and pushed it back to the server. That is... lets > just say not good. > > Hg is known to be more user friendly. One way its user friendly is it > by default refuses to let you amend a change set that the client has > reasonable assertion to believe was already published through a remote > repository. Well, it is not Git that is less user friendly, but Gerrit is the problem. More specifically, the last line: > git push URL HEAD:refs/for/master is what catches this non-fast-forward in usual workflow with Git. Wouldn't the real problem that the refs/for/master magic accepts anything, even a non-fast-forward? Having said that, disabling --amend and forcing to use --force or something when it is clear that the user is attempting something unusual is a good idea. But I am not sure what the definition of unusual should be. In a non-Gerrit central repository workflow, the rule might be "HEAD must not be reachable from @{upstream}" (otherwise you are rewriting what you got from elsewhere), or it may be "HEAD must not be reachable from @{publish}'s remote tracking branch", or perhaps both, as these two could be different in triangular workflow. But I am not sure what the sensible rules are when the user prepares the commit, planning to push it to a ref like refs/for/master that does not have a counterpart on our side. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: git commit --amend safety check? 2015-03-11 5:11 ` Junio C Hamano @ 2015-03-11 6:00 ` Shawn Pearce 2015-03-11 6:18 ` Junio C Hamano 2015-03-11 8:37 ` Peter Krefting 1 sibling, 1 reply; 8+ messages in thread From: Shawn Pearce @ 2015-03-11 6:00 UTC (permalink / raw) To: Junio C Hamano; +Cc: git On Tue, Mar 10, 2015 at 10:11 PM, Junio C Hamano <gitster@pobox.com> wrote: > Shawn Pearce <spearce@spearce.org> writes: > >> We keep seeing reports of Gerrit Code Review users who incorrectly do >> something like: >> >> git clone URL foo >> cd foo >> git commit --amend -m "My first change!" -a >> git push URL HEAD:refs/for/master >> >> Step #3 is where they get into trouble. They just amended the >> published tip commit and pushed it back to the server. That is... lets >> just say not good. >> >> Hg is known to be more user friendly. One way its user friendly is it >> by default refuses to let you amend a change set that the client has >> reasonable assertion to believe was already published through a remote >> repository. > > Well, it is not Git that is less user friendly, but Gerrit is the > problem. More specifically, the last line: > >> git push URL HEAD:refs/for/master > > is what catches this non-fast-forward in usual workflow with Git. OK, replace that Gerrit-specific push syntax with: git send-email :) Even in mailing list based workflows we ask Git users to use "git commit" to make their new commit and "git commit --amend" to polish it up. New users are often confused and cargo-culting their Git usage because they cannot be bothered to actually learn the tools they are using; they are too busy learning all of the other tools they need, like their programming language or the latest jQuery plugin. > Wouldn't the real problem that the refs/for/master magic accepts > anything, even a non-fast-forward? I see your argument. But this was a conscious design choice. It is already untenable to ask users sending you patches on git ML to first fetch and rebase *their* working tree against your latest master before they run git send-email. The async nature of when you publish your tree vs. when they prepared their commit makes it likely that at least some of the patches you receive were based on a different tip than what you most recently published. On very fast moving development repositories that have hundreds of developers working against them during the bulk of the working day the tip can be advancing more rapidly than users have the patience to run: while ! ( git pull --rebase && git push origin HEAD:refs/for/master ); do echo Retrying ... done > Having said that, disabling --amend and forcing to use --force or > something when it is clear that the user is attempting something > unusual is a good idea. But I am not sure what the definition of > unusual should be. In a non-Gerrit central repository workflow, the > rule might be "HEAD must not be reachable from @{upstream}" > (otherwise you are rewriting what you got from elsewhere), or it may > be "HEAD must not be reachable from @{publish}'s remote tracking > branch", or perhaps both, as these two could be different in > triangular workflow. > > But I am not sure what the sensible rules are when the user prepares > the commit, planning to push it to a ref like refs/for/master that > does not have a counterpart on our side. True. Another way users get into a bind is they pull someone else's branch (so they can build on top of her work), then `git commit --amend -a` by mistake instead of making a new commit. Now they mixed their work with her last commit. Then they push this. Currently Gerrit Code Review accepts that as an intentional squash to further polish her proposed change. And why not? I can take a patch proposed by Peff from the mailing list, `commit --amend` additional polishing, and resend with attribution^Wblame to Peff. Perhaps Gerrit Code Review should reject this by default unless the user has some sort of "Yes I know what I am doing" bit toggled on her user account. That only mildly helps the poor newbie who has no idea how to "unstick" their Git repository. Most users just rm -rf the directory, reclone, and start over from scratch, meanwhile complaining that "Git lost hours of their work". Nevermind that one could probably get out of such a jam with something like: git diff HEAD@{1}..HEAD >P git reset --hard HEAD@{1} git apply --index P ; rm P If only they knew how to use their tools. :( ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: git commit --amend safety check? 2015-03-11 6:00 ` Shawn Pearce @ 2015-03-11 6:18 ` Junio C Hamano 2015-03-11 6:33 ` Mike Hommey 2015-03-11 8:13 ` Jeff King 0 siblings, 2 replies; 8+ messages in thread From: Junio C Hamano @ 2015-03-11 6:18 UTC (permalink / raw) To: Shawn Pearce; +Cc: git On Tue, Mar 10, 2015 at 11:00 PM, Shawn Pearce <spearce@spearce.org> wrote: > > OK, replace that Gerrit-specific push syntax with: > > git send-email > > :) Heh don't be too defensive; I was merely pulling your leg. >> ... But I am not sure what the definition of >> unusual should be. In a non-Gerrit central repository workflow, the >> rule might be "HEAD must not be reachable from @{upstream}" >> (otherwise you are rewriting what you got from elsewhere), or it may >> be "HEAD must not be reachable from @{publish}'s remote tracking >> branch", or perhaps both, as these two could be different in >> triangular workflow. >> >> But I am not sure what the sensible rules are when the user prepares >> the commit, planning to push it to a ref like refs/for/master that >> does not have a counterpart on our side. > > True. With a more concrete example, I'd imagine you have something like this to wok on branch "master" [remote "origin"] url = ... pushurl = ... fetch = +refs/heads/*:refs/remotes/origin/* push = refs/heads/*:refs/for/* [branch "master"] merge = refs/heads/master Even though we cannot prevent the user from rewriting what _he_ already pushed out to refs/for/master (as we do not have the record of what the last thing we pushed there and its history via a reflog), we could at least detect when he attempts to rewrite what he obtained directly from the upstream by noticing where origin/master is. If HEAD is _at_ that commit, or its ancestor, then he is trying to rewrite what he got from elsewhere. It would catch your original "commit --amend -m 'my first'" scenario. Run is_ancestor(HEAD, @{upstream}) we can notice. That may be better than nothing, but I do not offhand know if that is sufficient. > Another way users get into a bind is they pull someone else's branch > (so they can build on top of her work), then `git commit --amend -a` > by mistake instead of making a new commit. One thing we already do is to give an extra "Author: " line in the comment when the user edits the log message, so that it is clear that what is being edited is not their own work but hers. We obviously can add the extra warning, when the is_ancestor() thing triggers, to say YOU ARE REWRITING PUBLISHED HISTORY in blinking red bold letters there. But the symptom indicates that they are not reading these warning comment. Perhaps it is necessary to introduce a training wheel mode where you cannot use "--amend" and "-m" options from the command line until you ask nicely to override it? ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: git commit --amend safety check? 2015-03-11 6:18 ` Junio C Hamano @ 2015-03-11 6:33 ` Mike Hommey 2015-03-11 8:13 ` Jeff King 1 sibling, 0 replies; 8+ messages in thread From: Mike Hommey @ 2015-03-11 6:33 UTC (permalink / raw) To: Junio C Hamano; +Cc: Shawn Pearce, git On Tue, Mar 10, 2015 at 11:18:45PM -0700, Junio C Hamano wrote: > One thing we already do is to give an extra "Author: " line in the > comment when the user edits the log message, so that it is clear > that what is being edited is not their own work but hers. We obviously > can add the extra warning, when the is_ancestor() thing triggers, to > say YOU ARE REWRITING PUBLISHED HISTORY in blinking red > bold letters there. > > But the symptom indicates that they are not reading these warning > comment. Maybe they would if the warnings were a big paragraph *before* the commit message (but brains are easily trained to recognize patterns and skip them, so that would need to be done for very specific warnings, not for everything that's printed in a git commit editor). Mike ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: git commit --amend safety check? 2015-03-11 6:18 ` Junio C Hamano 2015-03-11 6:33 ` Mike Hommey @ 2015-03-11 8:13 ` Jeff King 1 sibling, 0 replies; 8+ messages in thread From: Jeff King @ 2015-03-11 8:13 UTC (permalink / raw) To: Junio C Hamano; +Cc: Shawn Pearce, git On Tue, Mar 10, 2015 at 11:18:45PM -0700, Junio C Hamano wrote: > Even though we cannot prevent the user from rewriting what _he_ > already pushed out to refs/for/master (as we do not have the record > of what the last thing we pushed there and its history via a reflog), > we could at least detect when he attempts to rewrite what he > obtained directly from the upstream by noticing where origin/master > is. If HEAD is _at_ that commit, or its ancestor, then he is trying to > rewrite what he got from elsewhere. > > It would catch your original "commit --amend -m 'my first'" scenario. > Run is_ancestor(HEAD, @{upstream}) we can notice. That may be > better than nothing, but I do not offhand know if that is sufficient. I think rebase basically suffers the same problem, too. Perhaps it happens less there because we choose @{upstream} as the default fork point. But rewriting commits is a potential problem any time they are referenced somewhere else. For example, if you do this: git checkout -b topic origin/master ... commit commit commit ... git checkout -b subtopic ... commit commit commit ... git checkout topic git rebase ;# or git pull --rebase you are left with doppelganger commits in "subtopic", which you probably want to handle by rebasing it (with --fork-point). I kind of wonder if the check should just be "is the commit you are rewriting mentioned in _any_ ref except the current HEAD?". In theory we could even give advice based on the command and the ref we find that contains the commit (e.g., if it's another local branch, suggest rebasing that branch. If it's in @{upstream}, suggest "commit" without "--amend" if that was the command given). But I'm not at all confident that we could cover all cases thoroughly enough to do more good than harm. > > Another way users get into a bind is they pull someone else's branch > > (so they can build on top of her work), then `git commit --amend -a` > > by mistake instead of making a new commit. > > One thing we already do is to give an extra "Author: " line in the > comment when the user edits the log message, so that it is clear > that what is being edited is not their own work but hers. We obviously > can add the extra warning, when the is_ancestor() thing triggers, to > say YOU ARE REWRITING PUBLISHED HISTORY in blinking red > bold letters there. > > But the symptom indicates that they are not reading these warning > comment. Perhaps it is necessary to introduce a training wheel mode > where you cannot use "--amend" and "-m" options from the command > line until you ask nicely to override it? It's entirely possible to me that the "Author" line is too subtle, and a bigger warning might do the trick. At the very least printing a warning that can be suppressed with advice.* would match our usual technique for dealing with possible mistakes like this (as opposed to blocking the action entirely). And we can always bump the severity of the warning (or introduce blocking) if it doesn't have an effect. I dunno. It feels like such a warning would probably trigger as a false positive way too often and get in people's way. But then, I am not exactly the target audience for the warning, so my perspective is a bit skewed. I do think it has a reasonable chance of irritating old-timers, even with an escape hatch. Were you thinking that training-wheel mode would have to be turned on explicitly? -Peff ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: git commit --amend safety check? 2015-03-11 5:11 ` Junio C Hamano 2015-03-11 6:00 ` Shawn Pearce @ 2015-03-11 8:37 ` Peter Krefting 2015-03-11 17:56 ` Junio C Hamano 1 sibling, 1 reply; 8+ messages in thread From: Peter Krefting @ 2015-03-11 8:37 UTC (permalink / raw) To: Junio C Hamano; +Cc: Shawn Pearce, git Junio C Hamano: > Having said that, disabling --amend and forcing to use --force or > something when it is clear that the user is attempting something > unusual is a good idea. But I am not sure what the definition of > unusual should be. For commit --amend, I would say it would refuse to amend if the commit you are trying to amend 1. was not authored by yourself (and --reset-author was not given), or 2. is reachable (or is the tip?) from an upstream branch. Of course, you should be able to do the amend commit, but then you would need to say something like "git commit --amend --force" to indicate that you really want to do that. At least (1) would have saved myself from mistakes that take time and effort to clean up (I have used Git for eight years or so already, and I *still* do that kind of mistake every now and then). -- \\// Peter - http://www.softwolves.pp.se/ ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: git commit --amend safety check? 2015-03-11 8:37 ` Peter Krefting @ 2015-03-11 17:56 ` Junio C Hamano 0 siblings, 0 replies; 8+ messages in thread From: Junio C Hamano @ 2015-03-11 17:56 UTC (permalink / raw) To: Peter Krefting; +Cc: Shawn Pearce, git Peter Krefting <peter@softwolves.pp.se> writes: > For commit --amend, I would say it would refuse to amend if the commit > you are trying to amend > > 1. was not authored by yourself (and --reset-author was not given), or > 2. is reachable (or is the tip?) from an upstream branch. I agree that 2. is a safe check without too much risk to trigger a false positive (and the tip of origin/master is reachable from origin/master, so we do not have to single out "is the tip"). On the other hand, 1. may be good in training wheel mode, but once you start allowing amends and rebases, I do not see why it should be considered possibly bad as long as check 2. says it is OK to rewrite. > At least (1) would have saved myself from mistakes that take time and > effort to clean up (I have used Git for eight years or so already, and > I *still* do that kind of mistake every now and then). Isn't your friend reflog helping you to clean things up? The difference between the state before you started amending and the current state is what you did since then, so...? ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-03-11 17:56 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-03-11 4:31 git commit --amend safety check? Shawn Pearce 2015-03-11 5:11 ` Junio C Hamano 2015-03-11 6:00 ` Shawn Pearce 2015-03-11 6:18 ` Junio C Hamano 2015-03-11 6:33 ` Mike Hommey 2015-03-11 8:13 ` Jeff King 2015-03-11 8:37 ` Peter Krefting 2015-03-11 17:56 ` Junio C Hamano
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).