What is git staging and why does Hg *ostensibly* not support it?
Asked Answered
F

2

30

The Hg docs state that hg doesn't support an equivalent to git's index out of the box and suggests using extensions (record or mq) for similar behaviour.

First, I have very little field experience with git, so let me state my understanding of the concept of staging in git:

  • There's the working copy, containing a number of changed files, each having a number of changed chunks.
  • The user then (maybe repeatedly) uses git add to select which files will be committed.
  • Alternatively, use git add -p to select only some of the chunks in a file to later be committed.
  • Do a git commit to add the previously selected changes to the repository.

So the whole staging area, to me, is a pompous name for a selection of which of the changes in the working copy will make it in the next commit.

If I'm not completely off on that, then, why does everyone, including the official documentation, state that Mercurial does not support this?

I'm asking, because the exact workflow above is trivial in TortoiseHg:

enter image description here

  • in the left pane - select whole files to include in the commit
  • in the right bottom pane - select single chunks to include
  • hit 'Commit'.

I don't know what hg commands TortoiseHg uses, but then again, I never needed to care. (It doesn't make use of any extension for this AFAICT)

Is there more to the git concept of staging that I'm missing?

Farkas answered 6/2, 2014 at 16:49 Comment(0)
E
34

The staging area (index) records change snapshots, not just a selection of files. For instance, you can modify file A to add foo, stage file A, then modify file A again to add bar. If you don't re-stage file A, then when you commit, only foo will be committed, because the index has the snapshot of A when it was staged.

You can also revert a file back to the state of the last index snapshot (via git checkout). Essentially, the index acts like a "temporary commit" that is easy to modify before actually being promoted to a full commit.

Since the index is persistent, if you get halfway through staging things, then decide you need to make another change, no problem - just go make the change, then stage the new version. No need to re-stage all of the other things you've already staged.

Accidentally delete a file before committing? If you already staged it, no worries - just check out the staged version.

Elburr answered 6/2, 2014 at 16:54 Comment(5)
Good explanation. As a side note, gradual commits in the staging area can be mimicked in Mercurial by doing real commits of individual chunks as you work (instead of adding chunks to the staging area) and then streamlining these commits afterwards if needed (before pushing of course). The built-in histedit extension is a convenient tool for combining multiple commits to one.Wellpreserved
Ha! So the index is not just a "selection", but an actual tree, kind-of. Thanks - that puts things in perspective. I found a great article (by the author of Pro Git) explaining git reset for mere mortals, and it builds on this knowledge.Farkas
@CristiDiaconescu Not even "kind of" a tree - the index uses the exact same tree snapshot mechanism that commits do. :)Elburr
@Elburr In the article I mentioned in the comment above, the author says: "(Some Git developers will get a bit mad at me here, because there are a few cases where the Index doesn't exactly act like a tree, but for our purposes it is easier - forgive me)" and later: "It's not technically a tree structure, it's a flattened manifest[...]". I don't pretend to understand these intricacies - merely thought there are some subtle differences currently out of my reach. I'd love to know more about this.Farkas
It uses the same mechanism as tree objects do, it just doesn't worry about the directory nesting component until actually creating a commit.Elburr
A
11

Git was designed to support certain kind of workflow during Linux kernel development. By certain kind of people for certain kind of people.

It is not designed to be easy to use by ordinary developer (compare with hg!) but gain large popularity and cultural status due to its cost, performance, large company support and advertising campaign (GitHub here).

Today ordinary developer interact with Git via IDE GUI and don't need to know about Index/Stage area. It just uses checkboxes like in asker screen-shot (so there are no difference between Git/Mercurial usage for ordinary developer).

For people working with command line irregular CLI syntax of Git and exposing unnecessary storage format details make learning line longer in compare to time to become Mercurial wizard.

Here is nice images that describe Index usage:

You alway may emulate Index by (but why?):

hg qinit
hg qadd
hg qrefesh
hg qfinish

except MQ allow you to have an ordered set of Indexes, not just one! And allow you give name to each "Index".

With record extension you have option to select patch chunks in CLI like you check checkboxes in GUI. That extension is direct answer to Git -p option.

So topic starter is actually right in its filling that Index is unnecessary feature of DVCS architecture, and built into Git to support willing of some Git core developers.

Good luck and happy hacking!

UPDATE Quotation from http://stevebennett.me/2012/02/24/10-things-i-hate-about-git/

Most of the power of Git is aimed squarely at maintainers of codebases: people who have to merge contributions from a wide number of different sources, or who have to ensure a number of parallel development efforts result in a single, coherent, stable release. This is good. But the majority of Git users are not in this situation: they simply write code, often on a single branch for months at a time. Git is a 4 handle, dual boiler espresso machine – when all they need is instant.

Amaranthine answered 13/12, 2015 at 16:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.