Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ambiguity in the arrow for reset in first diagram #64

Closed
categulario opened this issue Jun 13, 2019 · 5 comments
Closed

ambiguity in the arrow for reset in first diagram #64

categulario opened this issue Jun 13, 2019 · 5 comments

Comments

@categulario
Copy link

In the diagram the command git reset -- files is pointing from the history towards the stage area:

Captura de pantalla de 2019-06-13 13-32-48

however in the description it is stated that:

git reset -- files unstages files; that is, it copies files from the latest commit to the stage. Use this command to "undo" a git add files. You can also git reset to unstage everything.

so there are conflicting statements here:

  • unstages files (implies from stage to WD)
  • copies files from the latest commit to the stage (implies from history to stage)
  • use this command to undo git add (since git add goes from WD to stage, this implies from stage to WD)

The specified usage (git reset -- files) implies an arrow in the same direction as git checkout. Perhaps is worth mentioning the git reset [--hard|--soft] tree-ish variant that actually follows the arrow in the diagram.

It relates to #20

@MarkLodato
Copy link
Owner

MarkLodato commented Jun 17, 2019

Hi categulario! You seem to have some confusion around what the terms "stage" and "unstage" mean. Both have a target of the stage. To "stage" something is to set up the index to be exactly what will be committed upon next git commit. To "unstage" is to undo a "stage" operation; that is, restore the index to its original state. The original state is precisely the same as the HEAD commit in history. That is why "unstage" (via git reset) copies content from the history to the stage.

In other words, the following statements in your original post are incorrect:

  • unstages files (implies from stage to WD)
  • use this command to undo git add (since git add goes from WD to stage, this implies from stage to WD)

Does that make sense?

Since this is the first time someone has brought up this issue in nine years, I don't think this is a particularly common issue so I will leave the text as-is.

@categulario
Copy link
Author

I guess that is is unclear or misleading whether the three boxes are areas of the index (btw stage is incorrectly labeled as the index since HEAD is also contained in it) or states of the tree: working directory clean, changes (staged and/or unstaged). Also the arrows have sometimes the function of moving the boundaries inside the index (git commit) or moving data (git checkout).

If the meaning of the arrows is moving data between areas within the index then the git reset is incorrectly placed as I suggest because git reset moves the boundary between the stage area and the unstaged area, and the HEAD (history) area remains untouched.

That is why "unstage" (via git reset) copies content from the history to the stage.

What is the content that gets copied from HEAD to the stage when unstaging?

The only reason I care about this is because someone was using this as reference with the result of more confusion about what was happening. Making this clear would make this a much better resource!

@MarkLodato
Copy link
Owner

I'm not sure where you are getting your information, but the index is a synonym for the stage. The link you provided does not contradict that. (In fact, it doesn't even have the word "HEAD.")

The arrows are always about moving data between three places: the history (i.e. commits), the stage / index, and the working directory. I don't understand what you mean by "moving boundaries."

That is why "unstage" (via git reset) copies content from the history to the stage.

What is the content that gets copied from HEAD to the stage when unstaging?

The original content of the file. Here is a concrete example.

First, create an initial repository and a handy alias for printing the contents of a given file in the three locations: history (HEAD), stage, and working directory.

$ mkdir /tmp/issue64
$ cd /tmp/issue64
$ git init
$ echo A > file.txt
$ git add file.txt
$ git commit -m 'initial commit'
$ function print_status() { printf 'HEAD: %s\nStage: %s\nWorking Directory: %s\n' "$(git show HEAD:$1)" "$(git show :$1)" "$(cat $1)" ; }
$ print_status file.txt
HEAD: A
Stage: A
Working Directory: A

Now let's set it up so that each has different contents.

$ echo B >! file.txt
$ git add file.txt
$ echo C >! file.txt
$ print_status file.txt
HEAD: A
Stage: B
Working Directory: C

Now, try staging a file via git add. Note that stage now matches the working directory.

$ git add file.txt
$ print_status file.txt
HEAD: A
Stage: C
Working Directory: C

And finally, try unstaging a file via git reset. See how the content is copied from HEAD?

$ git reset file.txt
$ print_status file.txt
HEAD: A
Stage: A
Working Directory: C

@categulario
Copy link
Author

https://stackoverflow.com/questions/4084921/what-does-the-git-index-contain-exactly#4086986

Because the index represents what is being tracked, and right after a commit, what is being tracked is identical to the last commit (git diff --cached returns nothing).

that is why you're seing that output using that definition of your print_status() function. Your function by it definition proves you right, but in the "staging" part is showing the contents of the commit HEAD is pointing to.

git diff [<options>] --cached [<commit>] [--] [<path>...]
           This form is to view the changes you staged for the next commit relative to the named <commit>. Typically you would want comparison with the latest commit, so if you do not give <commit>, it
           defaults to HEAD. If HEAD does not exist (e.g. unborn branches) and <commit> is not given, it shows all staged changes. --staged is a synonym of --cached.

perhaps you should be using this function instead.

Effectively, if what you want is to show the state of the stage you should use that:

https://stackoverflow.com/questions/1587846/how-do-i-show-the-changes-which-have-been-staged#1587877

which of course is going to be empty after commit.

@MarkLodato
Copy link
Owner

I'm sorry, I don't think there is anything more I can do to help you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants