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/other-helpers.asc
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -175,7 +175,7 @@ end
175
175
176
176
In one branch we change the word ``hello'' to ``hola'', then in another branch we change the ``world'' to ``mundo''.
177
177
178
-
image::../images/rerere1.png[]
178
+
image::images/rerere1.png[]
179
179
180
180
When we merge the two branches together, we'll get a merge conflict:
181
181
@@ -277,7 +277,7 @@ Recorded resolution for 'hello.rb'.
277
277
278
278
You can see that it "Recorded resolution for FILE".
279
279
280
-
image::../images/rerere2.png[]
280
+
image::images/rerere2.png[]
281
281
282
282
Now, let's undo that merge and then rebase it on top of our master branch instead. We can move our branch back by using `reset` as we saw in <<_reset>>.
283
283
@@ -337,7 +337,7 @@ index a440db6,54336ba..0000000
337
337
end
338
338
----
339
339
340
-
image::../images/rerere3.png[]
340
+
image::images/rerere3.png[]
341
341
342
342
You can also recreate the conflicted file state with the `checkout` command:
Copy file name to clipboardExpand all lines: book/07-git-tools/sections/replace.asc
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,7 +22,7 @@ c1822cf first commit
22
22
23
23
We want to break this up into two lines of history. One line goes from commit one to commit four - that will be the historical one. The second line will just be commits four and five - that will be the recent history.
24
24
25
-
image::../images/replace1.png[]
25
+
image::images/replace1.png[]
26
26
27
27
Well, creating the historical history is easy, we can just put a branch in the history and then push that branch to the master branch of a new remote repository.
28
28
@@ -37,7 +37,7 @@ c6e1e95 (history) fourth commit
37
37
c1822cf first commit
38
38
----
39
39
40
-
image::../images/replace2.png[]
40
+
image::images/replace2.png[]
41
41
42
42
Now we can push the new `history` branch to the `master` branch of our new repository:
43
43
@@ -82,7 +82,7 @@ $ echo 'get history from blah blah blah' | git commit-tree 9c68fdc^{tree}
82
82
The `commit-tree` command is one of a set of commands that are commonly referred to as 'plumbing' commands. These are commands that are not generally meant to be used directly, but instead are used by **other** Git commands to do smaller jobs. On occasions when we're doing weirder things like this, they allow us to do really low-level things but are not meant for daily use. You can read more about plumbing commands in <<_plumbing>>
83
83
=====
84
84
85
-
image::../images/replace3.png[]
85
+
image::images/replace3.png[]
86
86
87
87
OK, so now that we have a base commit, we can rebase the rest of our history on top of that with `git rebase --onto`. The `--onto` argument will be the SHA we just got back from `commit-tree` and the rebase point will be the third commit (the parent of the first commit we want to keep, `9c68fdc`):
88
88
@@ -94,7 +94,7 @@ Applying: fourth commit
94
94
Applying: fifth commit
95
95
----
96
96
97
-
image::../images/replace4.png[]
97
+
image::images/replace4.png[]
98
98
99
99
OK, so now we've re-written our recent history on top of a throw away base commit that now has instructions in it on how to reconstitute the entire history if we wanted to. We can push that new history to a new project and now when people clone that repository, they will only see the most recent two commits and then a base commit with instructions.
100
100
@@ -154,7 +154,7 @@ c1822cf first commit
154
154
155
155
Cool, right? Without having to change all the SHAs upstream, we were able to replace one commit in our history with an entirely different commit and all the normal tools (`bisect`, `blame`, etc) will work how we would expect them to.
156
156
157
-
image::../images/replace5.png[]
157
+
image::images/replace5.png[]
158
158
159
159
Interestingly, it still shows `81a708d` as the SHA, even though it's actually using the `c6e1e95` commit data that we replaced it with. Even if you run a command like `cat-file`, it will show you the replaced data:
Copy file name to clipboardExpand all lines: book/07-git-tools/sections/reset.asc
+18-18Lines changed: 18 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -90,42 +90,42 @@ $ tree
90
90
91
91
Git's main purpose is to record snapshots of your project in successively better states, by manipulating these three trees.
92
92
93
-
image::../images/reset-workflow.png[]
93
+
image::images/reset-workflow.png[]
94
94
95
95
Let's visualize this process: say you go into a new directory with a single file in it.
96
96
We'll call this *v1* of the file, and we'll indicate it in blue.
97
97
Now we run `git init`, which will create a Git repository with a HEAD reference which points to an unborn branch (`master` doesn't exist yet).
98
98
99
-
image::../images/reset-ex1.png[]
99
+
image::images/reset-ex1.png[]
100
100
101
101
At this point, only the Working Directory tree has any content.
102
102
103
103
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.
104
104
105
-
image::../images/reset-ex2.png[]
105
+
image::images/reset-ex2.png[]
106
106
107
107
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.
108
108
109
-
image::../images/reset-ex3.png[]
109
+
image::images/reset-ex3.png[]
110
110
111
111
If we run `git status`, we'll see no changes, because all three trees are the same.
112
112
113
113
Now we want to make a change to that file and commit it.
114
114
We'll go through the same process; first we change the file in our working directory.
115
115
Let's call this *v2* of the file, and indicate it in red.
116
116
117
-
image::../images/reset-ex4.png[]
117
+
image::images/reset-ex4.png[]
118
118
119
119
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.
120
120
Next we run `git add` on it to stage it into our Index.
121
121
122
-
image::../images/reset-ex5.png[]
122
+
image::images/reset-ex5.png[]
123
123
124
124
At this point if we run `git status` we will see the file in green
125
125
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
126
Finally, we run `git commit` to finalize the commit.
127
127
128
-
image::../images/reset-ex6.png[]
128
+
image::images/reset-ex6.png[]
129
129
130
130
Now `git status` will give us no output, because all three trees are the same again.
131
131
@@ -138,7 +138,7 @@ The `reset` command makes more sense when viewed in this context.
138
138
139
139
For the purposes of these examples, let's say that we've modified `file.txt` again and committed it a third time. So now our history looks like this:
140
140
141
-
image::../images/reset-start.png[]
141
+
image::images/reset-start.png[]
142
142
143
143
Let's now walk through exactly what `reset` does when you call it. It directly manipulates these three trees in a simple and predictable way.
144
144
It does up to three basic operations.
@@ -149,7 +149,7 @@ The first thing `reset` will do is move what HEAD points to.
149
149
This isn't the same as changing HEAD itself (which is what `checkout` does); `reset` moves the branch that HEAD is pointing to.
150
150
This means if HEAD is set to the `master` branch (ie, you're currently on the `master` branch), running `git reset 9e5e64a` will start by making `master` point to `9e5e64a`.
151
151
152
-
image::../images/reset-soft.png[]
152
+
image::images/reset-soft.png[]
153
153
154
154
No matter what form of `reset` with a commit you invoke, this is the first thing it will always try to do.
155
155
With `reset --soft`, it will simply stop there.
@@ -165,7 +165,7 @@ Note that if you run `git status` now you'll see in green the difference between
165
165
166
166
The next thing `reset` will do is to update the Index with the contents of whatever snapshot HEAD now points to.
167
167
168
-
image::../images/reset-mixed.png[]
168
+
image::images/reset-mixed.png[]
169
169
170
170
If you specify the `--mixed` option, `reset` will stop at this point.
171
171
This is also the default, so if you specify no option at all, this is where the command will stop.
@@ -178,7 +178,7 @@ You rolled back to before you ran all your `git add` and `git commit` commands.
178
178
The third thing that `reset` will do is to make the Working Directory look like the Index.
179
179
If you use the `--hard` option, it will continue to this stage.
180
180
181
-
image::../images/reset-hard.png[]
181
+
image::images/reset-hard.png[]
182
182
183
183
So let's think about what just happened.
184
184
You undid your last commit, the `git add` and `git commit` commands, **and** all the work you did in your working directory.
@@ -210,20 +210,20 @@ This form (since you did not specify a commit SHA or branch, and you didn't spec
210
210
211
211
So it essentially just copies `file.txt` from HEAD to the Index.
212
212
213
-
image::../images/reset-path1.png[]
213
+
image::images/reset-path1.png[]
214
214
215
215
This has the practical effect of _unstaging_ the file.
216
216
If we look at the diagram for that command and think about what `git add` does, they are exact opposites.
217
217
218
-
image::../images/reset-path2.png[]
218
+
image::images/reset-path2.png[]
219
219
220
220
This is why the output of the `git status` command suggests that you run this to unstage a file.
221
221
(See <<_unstaging>> for more on this.)
222
222
223
223
We could just as easily not let Git assume we meant ``pull the data from HEAD'' by specifying a specific commit to pull that file version from.
224
224
We would just run something like `git reset eb43bf file.txt`.
225
225
226
-
image::../images/reset-path3.png[]
226
+
image::images/reset-path3.png[]
227
227
228
228
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).
229
229
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.
@@ -242,15 +242,15 @@ You can use `reset` to quickly and easily squash them into a single commit that
242
242
Let's say you have a project where the first commit has one file, the second commit added a new file and changed the first, and the third commit changed the first file again.
243
243
The second commit was a work in progress and you want to squash it down.
244
244
245
-
image::../images/reset-squash-r1.png[]
245
+
image::images/reset-squash-r1.png[]
246
246
247
247
You can run `git reset --soft HEAD~2` to move the HEAD branch back to an older commit (the first commit you want to keep):
248
248
249
-
image::../images/reset-squash-r2.png[]
249
+
image::images/reset-squash-r2.png[]
250
250
251
251
And then simply run `git commit` again:
252
252
253
-
image::../images/reset-squash-r3.png[]
253
+
image::images/reset-squash-r3.png[]
254
254
255
255
Now you can see that your reachable history, the history you would push, now looks like you had one commit with `file-a.txt` v1, then a second that both modified `file-a.txt` to v2 and added `file-b.txt`.
256
256
@@ -279,7 +279,7 @@ HEAD will now point to `master`.
279
279
So, in both cases we're moving HEAD to point to commit A, but _how_ we do so is very different.
280
280
`reset` will move the branch HEAD points to, `checkout` moves HEAD itself.
Copy file name to clipboardExpand all lines: book/07-git-tools/sections/revision-selection.asc
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -265,7 +265,7 @@ For example, say you have a commit history that looks like <<double_dot>>.
265
265
266
266
[[double_dot]]
267
267
.Example history for range selection.
268
-
image::../images/double-dot.png[Example history for range selection.]
268
+
image::images/double-dot.png[Example history for range selection.]
269
269
270
270
You want to see what is in your experiment branch that hasn’t yet been merged into your master branch.
271
271
You can ask Git to show you a log of just those commits with `master..experiment` – that means ``all commits reachable by experiment that aren’t reachable by master.''
There are two ways to approach this problem, depending on what your desired outcome is.
14
14
@@ -18,7 +18,7 @@ If the unwanted merge commit only exists on your local repository, the easiest a
18
18
In most cases, if you follow the errant `git merge` with `git reset --merge ORIG_HEAD`, this will reset the branch pointers so they look like this:
19
19
20
20
.History after `git reset --merge`
21
-
image::../images/undomerge-reset.png[History after `git reset --merge`.]
21
+
image::images/undomerge-reset.png[History after `git reset --merge`.]
22
22
23
23
We covered `reset` back in <<_reset>>, so it shouldn't be too hard to figure out what's going on here.
24
24
Here's a quick refresher: `reset --hard` usually goes through three steps:
@@ -52,7 +52,7 @@ In this case, we want to undo all the changes introduced by merging in parent #2
52
52
The history with the revert commit looks like this:
53
53
54
54
.History after `git revert -m 1`
55
-
image::../images/undomerge-revert.png[History after `git revert -m 1`.]
55
+
image::images/undomerge-revert.png[History after `git revert -m 1`.]
56
56
57
57
The new commit `^M` has exactly the same contents as `C6`, so starting from here it's as if the merge never happened, except that the now-unmerged commits are still in `HEAD`'s history.
58
58
Git will get confused if you try to merge `topic` into `master` again:
@@ -67,7 +67,7 @@ There's nothing in `topic` that isn't already reachable from `master`.
67
67
What's worse, if you add work to `topic` and merge again, Git will only bring in the changes _since_ the reverted merge:
68
68
69
69
.History with a bad merge
70
-
image::../images/undomerge-revert2.png[History with a bad merge.]
70
+
image::images/undomerge-revert2.png[History with a bad merge.]
71
71
72
72
The best way around this is to un-revert the original merge, since now you want to bring in the changes that were reverted out, *then* create a new merge commit:
73
73
@@ -79,7 +79,7 @@ $ git merge topic
79
79
----
80
80
81
81
.History after re-merging a reverted merge
82
-
image::../images/undomerge-revert3.png[History after re-merging a reverted merge.]
82
+
image::images/undomerge-revert3.png[History after re-merging a reverted merge.]
83
83
84
84
In this example, `M` and `^M` cancel out.
85
85
`^^M` effectively merges in the changes from `C3` and `C4`, and `C8` merges in the changes from `C7`, so now `topic` is fully merged.
0 commit comments