-4

I have read many answers to this seemingly age-old question. But I have my own understanding and wanted to know if my understanding is correct or not.

Imagine I have a HTML, JS, CSS files I am working on. And in my next big release, my website will have a shiny new Title (maybe just a h1 tag) with a beautiful blue font (css styling). But no JS code is needed for this big release.

I make the change to the HTML file, and the CSS file of course, then I "git add" them both to the staging area. Since they are both in the staging area, I can now commit both these files with the changes and give them both the same label in my commit message that this commit "adds a beautiful blue title".

So perhaps without the staging area, I would not be able to package both files together under the same commit message but since I staged them together, its easier to understand that both of those files with the specific changes were what was done for the new shiny title on the website.

Is my thinking flawed? Any thoughts would be appreciated.

Baba.S
  • 324
  • 2
  • 14
  • Please see e.g. https://stackoverflow.com/q/49228209/3001761 - individually validating each person's understanding of a concept doesn't really scale across a site like SO! – jonrsharpe Jun 08 '20 at 16:02

2 Answers2

2

Here's how to to understand the staging area. I'll call it the "index".

First, some names:

  • The worktree is the files you see in your git-controlled folder.

  • The index is invisible.

  • The repo is an invisible collection of all commits.

Okay, here we go.

The first thing to understand is that every commit contains all your files. By that I mean that if you have commited files A, B, and C, and you then change just C and add-and-commit, there is a bad tendency to think that the resulting commit consists of "just C" or even "just the change in C". That is false. A commit is a complete snapshot of all the files.

Now, when you checkout a branch, which is always the start of operations, two things happen: the contents of the commit at the end of the branch are copied into the index and the worktree, both. So now, what you see (the worktree) and what's in the index are the same. If that branch's last commit contains A, B, and C in a certain state, now so does the worktree and so does the index.

So now we are ready for the edit-add-commit cycle:

  1. You edit a file in the worktree (let's pick C). That has no effect on the index.

  2. Next, you add that file; now the way C looks in the index matches the way it looks in the worktree, and vice versa. That is what "add" actually means.

  3. Finally, you commit, and what happens? Git looks only at the index. It just wraps all of those files up and snapshots them, kaboom. That means A as it was before, B as it was before, and C as modified because you did an add of C in the modified state.

Okay, so now we appreciate what the index is for. It is the place where you are constantly building what should go into the next commit.

Note that the index can be committed without corresponding to exactly what's in the worktree. You could modify C and D and add only C and commit. Now D is still sitting there modified in your worktree. No problem! That is why it is so nice to have a distinction between the worktree and the index.

So, to sum up: you work in the worktree. Based on your work, you construct the index; you can make it look as much like the worktree as you like, but it doesn't have to be identical to it. Finally, you commit, which mean you wrap up exactly the index as a commit. And on you go.


I should probably add: the files in the index are also the tracked files. When you say git status, git simply compares the contents of the index to the contents of the worktree and divides what it sees into various groups:

  • Things that are identical in both places. These are the tracked unmodified files. But git status does not bother to mention these, which is why people are so confused about what is "in" the index or what is "in" a commit.

  • Things that are present in both places but differ. These are the modified, tracked files.

  • Things that are present in one place but not the other. Git might remark upon these as untracked files, deleted files, and so on, depending on the nature of the difference.

matt
  • 515,959
  • 87
  • 875
  • 1,141
1

The staging area is like a box you put stuff to commit (freeze) into.

The purpose is what you stated: to box together everything before freezing.

Note that you might add something to the staging area now. Edit it. Now it will be both in the staging and as modified item. You'll need to add it again.

Daemon Painter
  • 3,208
  • 3
  • 29
  • 44