You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: book/07-git-tools/sections/reset.asc
+14-15Lines changed: 14 additions & 15 deletions
Original file line number
Diff line number
Diff line change
@@ -1,15 +1,15 @@
1
1
[[_git_reset]]
2
2
=== Reset Demystified
3
3
4
-
Before moving on to more specialized tools, let's talk about `reset` and `checkout`.
4
+
Before moving on to more specialized tools, let's talk about the Git `reset` and `checkout` commands.
5
5
These commands are two of the most confusing parts of Git when you first encounter them.
6
6
They do so many things that it seems hopeless to actually understand them and employ them properly.
7
7
For this, we recommend a simple metaphor.
8
8
9
9
==== The Three Trees
10
10
11
11
An easier way to think about `reset` and `checkout` is through the mental frame of Git being a content manager of three different trees.
12
-
By ``tree'' here we really mean ``collection of files'', not specifically the data structure.
12
+
By ``tree'' here, we really mean ``collection of files'', not specifically the data structure.
13
13
(There are a few cases where the index doesn't exactly act like a tree, but for our purposes it is easier to think about it this way for now.)
14
14
15
15
Git as a system manages and manipulates three trees in its normal operation:
@@ -26,7 +26,7 @@ Git as a system manages and manipulates three trees in its normal operation:
26
26
27
27
HEAD is the pointer to the current branch reference, which is in turn a pointer to the last commit made on that branch.
28
28
That means HEAD will be the parent of the next commit that is created.
29
-
It's generally simplest to think of HEAD as the snapshot of *your last commit*.
29
+
It's generally simplest to think of HEAD as the snapshot of *your last commit on that branch*.
30
30
31
31
In fact, it's pretty easy to see what that snapshot looks like.
32
32
Here is an example of getting the actual directory listing and SHA-1 checksums for each file in the HEAD snapshot:
@@ -46,7 +46,7 @@ $ git ls-tree -r HEAD
46
46
040000 tree 99f1a6d12cb4b6f19... lib
47
47
----
48
48
49
-
The `cat-file` and `ls-tree` commands are ``plumbing'' commands that are used for lower level things and not really used in day-to-day work, but they help us see what's going on here.
49
+
The Git `cat-file` and `ls-tree` commands are ``plumbing'' commands that are used for lower level things and not really used in day-to-day work, but they help us see what's going on here.
Again, here we're using `ls-files`, which is more of a behind the scenes command that shows you what your index currently looks like.
68
+
Again, here we're using `git ls-files`, which is more of a behind the scenes command that shows you what your index currently looks like.
69
69
70
-
The index is not technically a tree structure – it's actually implemented as a flattened manifest – but for our purposes it's close enough.
70
+
The index is not technically a tree structure -- it's actually implemented as a flattened manifest -- but for our purposes it's close enough.
71
71
72
72
===== The Working Directory
73
73
@@ -123,8 +123,7 @@ Next we run `git add` on it to stage it into our Index.
123
123
124
124
image::images/reset-ex5.png[]
125
125
126
-
At this point if we run `git status` we will see the file in green
127
-
under ``Changes to be committed'' because the Index and HEAD differ – that is, our proposed next commit is now different from our last commit.
126
+
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.
128
127
Finally, we run `git commit` to finalize the commit.
129
128
130
129
image::images/reset-ex6.png[]
@@ -203,7 +202,7 @@ The `reset` command overwrites these three trees in a specific order, stopping w
203
202
204
203
That covers the behavior of `reset` in its basic form, but you can also provide it with a path to act upon.
205
204
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.
206
-
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.
205
+
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.
207
206
But the Index and Working directory _can_ be partially updated, so reset proceeds with steps 2 and 3.
208
207
209
208
So, assume we run `git reset file.txt`.
@@ -237,7 +236,7 @@ So you can selectively unstage or revert content.
237
236
238
237
==== Squashing
239
238
240
-
Let's look at how to do something interesting with this newfound power – squashing commits.
239
+
Let's look at how to do something interesting with this newfound power -- squashing commits.
241
240
242
241
Say you have a series of commits with messages like ``oops.'', ``WIP'' and ``forgot this file''.
243
242
You can use `reset` to quickly and easily squash them into a single commit that makes you look really smart.
@@ -269,11 +268,11 @@ Like `reset`, `checkout` manipulates the three trees, and it is a bit different
269
268
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.
270
269
271
270
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.
272
-
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 in will be updated.
271
+
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 in will be updated.
273
272
`reset --hard`, on the other hand, will simply replace everything across the board without checking.
274
273
275
-
The second important difference is how it updates HEAD.
276
-
Where `reset` will move the branch that HEAD points to, `checkout` will move HEAD itself to point to another branch.
274
+
The second important difference is how `checkout` updates HEAD.
275
+
Whereas `reset` will move the branch that HEAD points to, `checkout` will move HEAD itself to point to another branch.
277
276
278
277
For instance, say we have `master` and `develop` branches which point at different commits, and we're currently on `develop` (so HEAD points to it).
279
278
If we run `git reset master`, `develop` itself will now point to the same commit that `master` does.
The other way to run `checkout` is with a file path, which, like `reset`, does not move HEAD.
291
290
It is just like `git reset [branch] file` in that it updates the index with that file at that commit, but it also overwrites the file in the working directory.
292
-
It would be exactly like `git reset --hard [branch] file` (if `reset` would let you run that) – it's not working-directory safe, and it does not move HEAD.
291
+
It would be exactly like `git reset --hard [branch] file` (if `reset` would let you run that) -- it's not working-directory safe, and it does not move HEAD.
293
292
294
293
Also, like `git reset` and `git add`, `checkout` will accept a `--patch` option to allow you to selectively revert file contents on a hunk-by-hunk basis.
295
294
@@ -299,7 +298,7 @@ Hopefully now you understand and feel more comfortable with the `reset` command,
299
298
300
299
Here's a cheat-sheet for which commands affect which trees.
301
300
The ``HEAD'' column reads ``REF'' if that command moves the reference (branch) that HEAD points to, and ``HEAD'' if it moves HEAD itself.
302
-
Pay especial attention to the 'WD Safe?' column – if it says *NO*, take a second to think before running that command.
301
+
Pay especial attention to the 'WD Safe?' column -- if it says *NO*, take a second to think before running that command.
0 commit comments