0

What is the mercurial equivalent to git checkout -? I want to go to wherever I last was.

I tried hg checkout -, but that yields a parse error.

Max Heiber
  • 14,346
  • 12
  • 59
  • 97
  • "I want to go to wherever I last was" -- can you elaborate on this a bit more? – StayOnTarget Jun 10 '21 at 11:58
  • Sure: what `git checkout -` does. For example, after `git checkout foo && git checkout bar && git checkout -` one ends up at ref `foo`. After `hg update foo && hg update bar` what can I type to go back to `foo` without mentioning `foo` directly (to save keypresses and inspecting logs)?. – Max Heiber Jun 11 '21 at 15:44
  • Wish I knew more git :( So after doing just `git checkout foo && git checkout bar` what would be the state of things at that point? Doesn't it basically make the working folders look like whatever was committed at `bar` ? – StayOnTarget Jun 11 '21 at 15:52
  • I guess I'm trying to understand the underlying workflow and objective, so that I can think about what the HG equivalent might be. – StayOnTarget Jun 11 '21 at 15:53
  • 1
    @StayOnTarget correct, `git checkout` is roughly `hg update` . The use case of `git checkout -` is to jump around quickly between different commits. Such as "work on bookmark foo, switch to bookmark bar to look at some code for reference, switch back to where I started easily". Take `cd` as an anology: if there are too dirs: `dir_foo` and `dir_bar`, one can do `cd dir_foo && cd dir_bar && cd -` and end up at `dir_foo`. `git checkout -` is like `cd -` but for branches instead of directories. – Max Heiber Jun 11 '21 at 16:38
  • Would you literally run those commands serially with `&&` ? If so , would it have any effect? – StayOnTarget Jun 11 '21 at 16:39
  • I would not literally run the commands serially with `&&`. An example use case is "work on bookmark foo, switch to bookmark bar to look at some code for reference, switch back to where I started easily". This is a thing people really do with git - see this StackOverflow answer that references `git checkout -`: https://stackoverflow.com/a/7207542/2482570 and Unix StackExchange answer about `cd -`: https://unix.stackexchange.com/questions/81224/how-to-go-to-the-previous-working-directory-in-terminal – Max Heiber Jun 11 '21 at 16:41
  • Thanks for all the explanation, you're answering my questions instead of the other way around :) I do a similar workflow in HG often as well... wish I could think of a precise way to do what you want however. As far as I know HG does not maintain any *history* of the *working directory*. So maybe this is not possible out of the box. – StayOnTarget Jun 11 '21 at 16:43
  • Incidentally since you mentioned bookmarks - check out `hg topic` sometime, its close to git branches as I understand it. – StayOnTarget Jun 11 '21 at 16:44

1 Answers1

1

There isn't one.

The - here in Git is shorthand for @{-1}, which refers to the reflog for HEAD. While Git's branches are much more like Mercurial's bookmarks than anything else, every time you switch branches, Git writes an entry to a reflog saying before switching, the current branch was <name>. A subsequent @{-number} means scan through this particular reflog looking for such entries, count until you hit the number-th such entry, and use that branch name as the name here. For this to work, the system must maintain this log of checkout operations, storing the old name whenever a new name is supplied. I'm glossing over Git's so-called detached HEAD mode here: @{-number} refers to both names and raw hash IDs. Mercurial has nothing like Git's "detached HEAD" mode: you're always on some branch. Mercurial branches are real, solid things, unlike Git's branches, which evaporate while leaving the commits around: In Git, commits are on many branches simultaneously, which is quite nonsensical in Mercurial, but sensible enough in Git, and deleting a branch just takes away one of the many names that allow Git to find the commits.

Since Mercurial does not retain a log of each hg update, there is no way to retrieve a previous update argument from the log. [Edit: there is the experimental Journal extension; see Max Heiber's comment.] You could of course write your own little wrapper that runs hg update and, if the update succeeds, logs which commit and/or branch was in use just before the update. This wrapper could then implement the "update back" operation.

Side note: The hg topics command that StayOnTarget mentioned in a comment is part of the evolve extension. This gives Mercurial the ability to do things Git just can't do. It's not the same as using Git branches at all. Mercurial without evolve can already do the same things Git can do, and a bit more (because Mercurial branchs are real). However, the permanance of branches, while attractive at first blush, is in my opinion often a net negative (by which I mean "you should use bookmarks first, and maybe only"). But the evolve extensions are are a feature sorely missing from both Mercurial and Git; they're available in Mercurial, but not part of the standard distributions and require extra user knowledge (see also the roadmap and its links).

torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks! A few small corrections: `git checkout -` doesn't go to the previous branch, it goes to wherever `HEAD` was last - which can be any ref, including commits that aren't on any branches. So the paragraphs about differences in branching philosophy between git and hg are probably not relevant. And `hg`, at least the one I got via homebrew, does have something that seems a lot like `reflog` - `hg journal` (experimental extension): https://www.mercurial-scm.org/wiki/JournalExtension – Max Heiber Jun 13 '21 at 17:25
  • 1
    @MaxHeiber: that's why I said I was glossing over detached-HEAD stuff. Since Mercurial lacks this concept entirely, there was no point covering it here, but I have a tendency to want to be *technically correct* so I introduced it in this sideways fashion. :-) Separately: I wasn't aware of the Journal extension though, that's kind of handy. – torek Jun 14 '21 at 07:09