Morten Welinder [off-list ref] writes:
quoted
While I am sympathetic, this "Oops, I said pull when I meant
fetch" sounds remotely similar to "oops, I said 'rm -r' when I
meant to say 'ls -r'". Is it that the tool is too fragile?
Didn't bk come with some kind of (one-level) undo pull? It should not
be too hard to create something similar considering that one could
just leave new objects in the db orphaned.
Yes, that is called "git reset".
On Fri, 16 Dec 2005, Junio C Hamano wrote:
Morten Welinder [off-list ref] writes:
quoted
quoted
While I am sympathetic, this "Oops, I said pull when I meant
fetch" sounds remotely similar to "oops, I said 'rm -r' when I
meant to say 'ls -r'". Is it that the tool is too fragile?
Didn't bk come with some kind of (one-level) undo pull? It should not
be too hard to create something similar considering that one could
just leave new objects in the db orphaned.
Yes, that is called "git reset".
Well, this is one area where BK and git differ a lot. BK didn't overload
many things onto the same "reset" functionality, but had specific
operations for specific cases.
Also BK would never leave a merge in the git kind of half-merged state,
because BK refuses to have two branches open. Instead, BK had a special
way of handling merges, which worked fine but quite frankly I have very
little idea of how it worked (it was some kind of "shadow BK tree", it was
called ".bk/RESOLVE/" or something like that - but because the tools
were so nice, you never really had any reason to look into it, so I
don't know what it did).
BK would never change the working tree itself until the merge was done, so
you would never need to do what a plain "git reset --hard" (without any
arguments) does.
In many ways the BK thing was very nice, although the git way is perhaps a
bit more flexible (because git makes the intermediate tree visible you can
easily edit the merge errors, and compile/test the result, before you
decide to commit any manual merge).
I really do like the way git does merges now (especially after the last
round of git-diff-tree fixes that allow comparing the different stages),
but the BK way is in some ways cleaner and leaves less potential for
confusion since it avoids ever exposing you to any half-merged state.
You may remember how I initially argued that we should always try to merge
stuff outside of the normal working directory. And I still _like_ that
approach, although I've since decided that I actually prefer the current
git way is even better in practice.
But "git reset" is a lot more than the "revert to previous state". It
_also_ does - without the error checking - what "bk fix" used to do
(which is to undo the last commit, so that you can re-commit it), and it
also does what "bk undo" used to do. It also does "bk unpull".
So "git reset" really does a whole lot of different and _mostly_ related
things:
- undo any half-way changes (very similar to just "git checkout -f"), and
just reset to the state of the last successful commit (ie "current
HEAD"):
git reset --hard
BK didn't need this, although if you just want to remove your edits
(which "git reset --hard" also does), you could - like with git - just
do a "checkout" operation, of course.
- undo the last commit, but don't undo the working tree ("soft reset to
parent of head").
git reset HEAD^
I think this was "bk fix -C".
- undo the last commit entirely ("hard reset to previous state"):
git reset --hard HEAD^
This was "bk undo"
- undo the last pull ("bk unpull"): "hard reset to ORIG_HEAD":
git reset --hard ORIG_HEAD
This was "bk unpull".
where the last two are obviously just special cases of a generic "undo to
arbitrary previous commit state".
BK in many ways had more hand-holding (which I think is good, and "git" to
some degree has an unnecessarily "hard core" approach to these things).
For example, I think "bk undo" not only asked you about it, but it also
only ever undid the last commit (and refused to undo a pull or merge). If
you wanted to undo to some arbitrary state, you had to use the "-a" flag,
iirc.
Of course, under BK the "undo" operation was final, so BK _had_ to be more
careful. With git, if you undo to some arbitrary state, you can still
"re-do" all your commits if you just find the old head (and
git-fsck-objects will help you do that), so in that sense git doesn't
_need_ to be as careful as BK was.
Linus
- undo the last commit entirely ("hard reset to previous state"):
git reset --hard HEAD^
This was "bk undo"
- undo the last pull ("bk unpull"): "hard reset to ORIG_HEAD":
git reset --hard ORIG_HEAD
This was "bk unpull".
It would be outright peachy if Documentation/git-commit.txt and
Documentation/git-pull.txt mentioned these. That is certainly
where I would look first to answer the "what if I screwed up?"
question.
Morten
On Fri, 16 Dec 2005, Morten Welinder wrote:
It would be outright peachy if Documentation/git-commit.txt and
Documentation/git-pull.txt mentioned these. That is certainly
where I would look first to answer the "what if I screwed up?"
question.
It might be even better to have some of the "safe" versions around. Ie
something that refuses to "undo" a merge (you want to "unpull" it or
"unmerge" it), and refuses to "undo" when there's a ORIG_HEAD around that
implies that the last commit was a "pull" (in which case again "undo" may
be the wrong thing to do, since it will only undo _one_ commit, even
though the pull might have fast-forwarded a _lot_ of commits).
Of course, if we do that, we should also make sure that "git commit"
removes ORIG_HEAD.
Or maybe "git commit" should always _write_ ORIG_HEAD with the old head,
so that we can always do an "undo" by doing "git reset --hard ORIG_HEAD"
regardless of whether the last thing was a "git commit" or a "git pull".
Hmm?
Linus