3

Perhaps I am over-thinking this, but can someone elaborate on the following statement?

Counterintuitively, rebases and merges are stateful, and git can cede control back to you before a merge/rebase is finished.

After a brief review of state, I believe this has to do with rebases and merges consisting of serial (sequential) steps, where each step is an atomic change and thus it can be rolled back. Is this correct? Can someone explain this better, and why this is counterintuitive? If rebase and merge weren't stateful, would they be irreversible?

Finally, are rebase and merge stateful only in Git?

modulitos
  • 14,737
  • 16
  • 67
  • 110
  • 3
    "and git can cede control back to you" --- I'm sure it implicitly mentions merge conflicts that must be resolved manually. So they are stateful because not every merge/rebase might be performed in the same way <---- just a guess. – zerkms Sep 25 '14 at 04:41

3 Answers3

4

It means that git stores state information inside the .git directory that it uses to keep track of what it is doing.

To see it for a merge type git merge --no-commit <some branch> and then ls -l .git and you will see the files MERGE_HEAD, MERGE_MODE, and MERGE_MSG have been created. When the merge is committed those files are removed.

For a rebase, just do something like git rebase -i HEAD~1, and change any line from "pick" to "edit". When git gives control back to you do ls -l .git and you will see there is a .git/rebase-merge directory created with a whole bunch of files it, including the list of rebase actions to still be performed. git rebase --abort (or when the rebase ends on its own) and those files are deleted.

I have no idea why the person who said that thought either of these operations having state was counter-intuitive. If you are chunking commits one at a time via rebase you have to have a 'todo' list stored somewhere. And if you are merging you have to know what the merged in SHA is so you commit at it in addition to HEAD.

Andrew C
  • 13,845
  • 6
  • 50
  • 57
  • I'd called it counterintuitive only because it may not be intuitive to a new git user that the repository is in the middle of a process if they get back to a shell prompt. Subversion, for instance, will interactively ask for conflict resolution before returning control to the user. – Jeff Bowman Sep 25 '14 at 05:57
2

As the original poor explainer commenter, I can clarify what I meant there.

Unlike many git commands (such as checkout), which update your repo/index/workdir and then return control back to you, it is possible for git to exit in the middle of a merge or rebase and give control back to the user. This is particularly important because it gives you a chance to resolve merge conflicts before continuing your merge or rebase.

git merge --abort
git rebase --continue | --skip | --abort | --edit-todo

If a merge fails, git will show you this message:

Automatic merge failed; fix conflicts and then commit the result.

And during a rebase, git will show you this message:

Failed to merge in the changes.

Patch failed at (step)

When you have resolved this problem run "git rebase --continue". If you would prefer to skip this patch, instead run "git rebase --skip". To restore the original branch and stop rebasing run "git rebase --abort".

In either case running git status will list some files as

# Unmerged paths:
#   (use "git add/rm ..." as appropriate to mark resolution)
#
#   both modified:      YOURFILE
#

It's not particularly counterintuitive, unless you expect git to either succeed entirely or fail immediately before returning control to you. You can also find yourself in trouble if you leave a directory in the middle of a merge or rebase, forget about it, and return to it later expecting to operate it as normal. One helpful technique is to add your branch name and merge state onto your shell prompt, which I've found helpful to remember which state my working directory is in at any given time.

Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
1

Pretty simply, once you start a merge or rebase, it's "in process." It's not finished yet, and you need to either roll back it or commit it. You can't make other major git commands (like commits) intermediately.

djechlin
  • 59,258
  • 35
  • 162
  • 290
  • Well, rebase (especially interactive rebase) deliberately stops and lets you do commits. But generally when you're in the middle of a rebase or merge, and dealing with conflicts, you don't want to start something else big, yes. – torek Sep 25 '14 at 05:02