From cdeeb75b46fe829cf2afaa3508b14d9bb74b17e4 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Sun, 17 Feb 2019 05:29:35 -0500 Subject: [PATCH] Reset demystified: Some semantic cleanup, and much de-capitalization In addition to some semantic tidying up, de-capitalize the terms "index" and "working directory", as those terms are not normally capitalized in the official Git docs. Signed-off-by: Robert P. J. Day --- book/07-git-tools/sections/reset.asc | 54 ++++++++++++++-------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/book/07-git-tools/sections/reset.asc b/book/07-git-tools/sections/reset.asc index 0c4fb87d4..17962c60a 100644 --- a/book/07-git-tools/sections/reset.asc +++ b/book/07-git-tools/sections/reset.asc @@ -51,7 +51,7 @@ The Git `cat-file` and `ls-tree` commands are ``plumbing'' commands that are use [[_the_index]] ===== The Index -The Index is your *proposed next commit*. +The _index_ is your *proposed next commit*. We've also been referring to this concept as Git's ``Staging Area'' as this is what Git looks at when you run `git commit`. Git populates this index with a list of all the file contents that were last checked out into your working directory and what they looked like when they were originally checked out. @@ -71,10 +71,10 @@ The index is not technically a tree structure -- it's actually implemented as a ===== The Working Directory -Finally, you have your working directory. +Finally, you have your _working directory_ (also commonly referred to as the ``working tree''). The other two trees store their content in an efficient but inconvenient manner, inside the `.git` folder. -The Working Directory unpacks them into actual files, which makes it much easier for you to edit them. -Think of the Working Directory as a *sandbox*, where you can try changes out before committing them to your staging area (index) and then to history. +The working directory unpacks them into actual files, which makes it much easier for you to edit them. +Think of the working directory as a *sandbox*, where you can try changes out before committing them to your staging area (index) and then to history. [source,console] ---- @@ -90,7 +90,7 @@ $ tree ==== The Workflow -Git's main purpose is to record snapshots of your project in successively better states, by manipulating these three trees. +Git's typical workflow is to record snapshots of your project in successively better states, by manipulating these three trees. image::images/reset-workflow.png[] @@ -100,30 +100,30 @@ Now we run `git init`, which will create a Git repository with a HEAD reference image::images/reset-ex1.png[] -At this point, only the Working Directory tree has any content. +At this point, only the working directory tree has any content. -Now we want to commit this file, so we use `git add` to take content in the Working Directory and copy it to the Index. +Now we want to commit this file, so we use `git add` to take content in the working directory and copy it to the index. image::images/reset-ex2.png[] -Then we run `git commit`, which takes the contents of the Index and saves it as a permanent snapshot, creates a commit object which points to that snapshot, and updates `master` to point to that commit. +Then we run `git commit`, which takes the contents of the index and saves it as a permanent snapshot, creates a commit object which points to that snapshot, and updates `master` to point to that commit. image::images/reset-ex3.png[] If we run `git status`, we'll see no changes, because all three trees are the same. Now we want to make a change to that file and commit it. -We'll go through the same process; first we change the file in our working directory. +We'll go through the same process; first, we change the file in our working directory. Let's call this *v2* of the file, and indicate it in red. image::images/reset-ex4.png[] -If we run `git status` right now, we'll see the file in red as ``Changes not staged for commit,'' because that entry differs between the Index and the Working Directory. -Next we run `git add` on it to stage it into our Index. +If we run `git status` right now, we'll see the file in red as ``Changes not staged for commit,'' because that entry differs between the index and the working directory. +Next we run `git add` on it to stage it into our index. image::images/reset-ex5.png[] -At this point, if we run `git status`, we will see the file in green under ``Changes to be committed'' because the Index and HEAD differ -- that is, our proposed next commit is now different from our last commit. +At this point, if we run `git status`, we will see the file in green under ``Changes to be committed'' because the index and HEAD differ -- that is, our proposed next commit is now different from our last commit. Finally, we run `git commit` to finalize the commit. image::images/reset-ex6.png[] @@ -131,7 +131,7 @@ image::images/reset-ex6.png[] Now `git status` will give us no output, because all three trees are the same again. Switching branches or cloning goes through a similar process. -When you checkout a branch, it changes *HEAD* to point to the new branch ref, populates your *Index* with the snapshot of that commit, then copies the contents of the *Index* into your *Working Directory*. +When you checkout a branch, it changes *HEAD* to point to the new branch ref, populates your *index* with the snapshot of that commit, then copies the contents of the *index* into your *working Directory*. ==== The Role of Reset @@ -159,14 +159,14 @@ With `reset --soft`, it will simply stop there. Now take a second to look at that diagram and realize what happened: it essentially undid the last `git commit` command. When you run `git commit`, Git creates a new commit and moves the branch that HEAD points to up to it. -When you `reset` back to `HEAD~` (the parent of HEAD), you are moving the branch back to where it was, without changing the Index or Working Directory. -You could now update the Index and run `git commit` again to accomplish what `git commit --amend` would have done (see <<_git_amend>>). +When you `reset` back to `HEAD~` (the parent of HEAD), you are moving the branch back to where it was, without changing the index or working directory. +You could now update the index and run `git commit` again to accomplish what `git commit --amend` would have done (see <<_git_amend>>). ===== Step 2: Updating the Index (--mixed) -Note that if you run `git status` now you'll see in green the difference between the Index and what the new HEAD is. +Note that if you run `git status` now you'll see in green the difference between the index and what the new HEAD is. -The next thing `reset` will do is to update the Index with the contents of whatever snapshot HEAD now points to. +The next thing `reset` will do is to update the index with the contents of whatever snapshot HEAD now points to. image::images/reset-mixed.png[] @@ -178,7 +178,7 @@ You rolled back to before you ran all your `git add` and `git commit` commands. ===== Step 3: Updating the Working Directory (--hard) -The third thing that `reset` will do is to make the Working Directory look like the Index. +The third thing that `reset` will do is to make the working directory look like the index. If you use the `--hard` option, it will continue to this stage. image::images/reset-hard.png[] @@ -187,7 +187,7 @@ So let's think about what just happened. You undid your last commit, the `git add` and `git commit` commands, *and* all the work you did in your working directory. It's important to note that this flag (`--hard`) is the only way to make the `reset` command dangerous, and one of the very few cases where Git will actually destroy data. -Any other invocation of `reset` can be pretty easily undone, but the `--hard` option cannot, since it forcibly overwrites files in the Working Directory. +Any other invocation of `reset` can be pretty easily undone, but the `--hard` option cannot, since it forcibly overwrites files in the working directory. In this particular case, we still have the *v3* version of our file in a commit in our Git DB, and we could get it back by looking at our `reflog`, but if we had not committed it, Git still would have overwritten the file and it would be unrecoverable. ===== Recap @@ -195,23 +195,23 @@ In this particular case, we still have the *v3* version of our file in a commit The `reset` command overwrites these three trees in a specific order, stopping when you tell it to: 1. Move the branch HEAD points to _(stop here if `--soft`)_ -2. Make the Index look like HEAD _(stop here unless `--hard`)_ -3. Make the Working Directory look like the Index +2. Make the index look like HEAD _(stop here unless `--hard`)_ +3. Make the working directory look like the index ==== Reset With a Path That covers the behavior of `reset` in its basic form, but you can also provide it with a path to act upon. If you specify a path, `reset` will skip step 1, and limit the remainder of its actions to a specific file or set of files. This actually sort of makes sense -- HEAD is just a pointer, and you can't point to part of one commit and part of another. -But the Index and Working directory _can_ be partially updated, so reset proceeds with steps 2 and 3. +But the index and working directory _can_ be partially updated, so reset proceeds with steps 2 and 3. So, assume we run `git reset file.txt`. This form (since you did not specify a commit SHA-1 or branch, and you didn't specify `--soft` or `--hard`) is shorthand for `git reset --mixed HEAD file.txt`, which will: 1. Move the branch HEAD points to _(skipped)_ -2. Make the Index look like HEAD _(stop here)_ +2. Make the index look like HEAD _(stop here)_ -So it essentially just copies `file.txt` from HEAD to the Index. +So it essentially just copies `file.txt` from HEAD to the index. image::images/reset-path1.png[] @@ -228,8 +228,8 @@ We would just run something like `git reset eb43bf file.txt`. image::images/reset-path3.png[] -This effectively does the same thing as if we had reverted the content of the file to *v1* in the Working Directory, ran `git add` on it, then reverted it back to *v3* again (without actually going through all those steps). -If we run `git commit` now, it will record a change that reverts that file back to *v1*, even though we never actually had it in our Working Directory again. +This effectively does the same thing as if we had reverted the content of the file to *v1* in the working directory, ran `git add` on it, then reverted it back to *v3* again (without actually going through all those steps). +If we run `git commit` now, it will record a change that reverts that file back to *v1*, even though we never actually had it in our working directory again. It's also interesting to note that like `git add`, the `reset` command will accept a `--patch` option to unstage content on a hunk-by-hunk basis. So you can selectively unstage or revert content. @@ -268,7 +268,7 @@ Like `reset`, `checkout` manipulates the three trees, and it is a bit different Running `git checkout [branch]` is pretty similar to running `git reset --hard [branch]` in that it updates all three trees for you to look like `[branch]`, but there are two important differences. First, unlike `reset --hard`, `checkout` is working-directory safe; it will check to make sure it's not blowing away files that have changes to them. -Actually, it's a bit smarter than that -- it tries to do a trivial merge in the Working Directory, so all of the files you _haven't_ changed will be updated. +Actually, it's a bit smarter than that -- it tries to do a trivial merge in the working directory, so all of the files you _haven't_ changed will be updated. `reset --hard`, on the other hand, will simply replace everything across the board without checking. The second important difference is how `checkout` updates HEAD.