-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path06-tips.Rmd
More file actions
197 lines (111 loc) · 8.41 KB
/
06-tips.Rmd
File metadata and controls
197 lines (111 loc) · 8.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# Common issues & tips
This section outlines some common issues you may run into, and how to fix them, as well as describing a few useful commands to make Git a little more user friendly.
## Common issues and how to fix them
### I've realised I made an error in my commit
If you've just committed some changes but realised a mistake in them you can "amend" the commit. However, this should be done before you push your changes! Things can get complicated if you try amending public commits.
To amend the commit, correct the file, add the file in Git and then use this command to combine the correction into the previous commit:
``` sh
git commit --amend
```
(Technically this combines both commits into a new commit that overwrites the last one).
If you've made a typo in your commit message you can also correct it with amend. Say your last commit looks like this:
109563e Some User | 2018/01/27 10:44 Added mew featuere
Adding the `-m` flag to your amend allows you to add a new comment.
``` sh
git commit --amend -m "Added new feature"
```
Your history will then look like this:
23237f1 Some User | 2018/01/27 10:44 Added new feature
### I want to go back to an earlier commit {#reset-revert}
You've made some changes that didn't work out for whatever reason, and now want to return your code to an earlier state. There are two ways to do this: *reset* and *revert*.
#### Reset
This option will "roll back" your directory to its earlier state, essentially going back in time and removing any changes since the commit you go back to.
Use
git reset --hard <commit-hash>
where `<commit-hash>` is the unique hash of the commit you want to go back to (you can find this via `git log`).
The `--hard` option in this command means that your working directory and staging area will also be reset, which is usually what you want, but **be careful as you will lose any uncommitted changes when you use this command**.
#### Revert
This option keeps all the changes you have made, but adds an extra commit with new changes that *reverse* the previous changes.
You will usually want to use
git revert HEAD
to revert the most recent commit (which is what the `HEAD` in this command refers to).
Reverting anything other than the most recent commit is **not recommended**.
If you want to revert multiple commits at once, you can use something of the form
git revert --no-commit HEAD~2^..HEAD
followed by
git commit -m "Reverted last three commits"
Walking through this:
- The `--no-commit` part of the command means that the reversion will change the working directory and staged files, but not yet be committed. (You'll have seen that we commit it afterwards, which is the usual way to work when reverting multiple commits at once).
- `HEAD~2^` means the commit two commits before `HEAD` (and e.g. `HEAD~4^` would be the commit four commits before `HEAD`)
- `..` indicates to include all commits between the two specified
So the first command reverts the most recent commit and the two before it - three commits in all - but only makes those changes in the working directory and staging area rather than committing them. Then the second command is a standard commit command which commits them all with a message.
#### When should I use reset vs revert?
The two commands will result in a different git history. With `reset`, any changes you roll back will not appear, giving a shorter history; with `revert`, everything that happened will be recorded and the history will be longer. So if it's not necessary for anyone to know about the rolled back changes, `reset` is probably better; if you need a record of what happened then `revert` is probably better.
There are a few other important considerations too:
- You need to be a bit more careful when using `reset`, as it will erase any uncommitted changes and you'll be unable to recover them.
- If any of the changes you want to reverse have been pushed to a remote server, you should use `revert` so that it's clear to others that changes have been rolled back. Using `reset` on a shared history will create confusion because it will not be clear what has happened.
- You can't (easily) `revert` past a merge because it's unclear which merged branch you want to revert to. `reset` is easier to use when the history you want to roll back includes a merge.
### I've worked on the wrong branch (but haven't committed yet)
You've made some changes to your code, saved them, but realised that you've been working on the wrong branch before committing. Fortunately, this is pretty easy to solve. The **git stash** command is your friend here: it allows you to store all your file changes away since the last commit away, and bring them back where you want - usually on a new branch.
The commands are: store away any changes with
``` sh
git stash
```
(If you check `git status` at this point you'll see that your file changes since your last commit no longer appear.)
Then switch branch with
``` sh
git checkout <your_branch>
```
and use
``` sh
git stash pop
```
to bring your changes back. That's it!
Using the **pop** command does *not* commit your changes - you have simply moved uncommitted changes from one branch to another - and once you have "popped" your changes they will be removed from the stash.
Occasionally popping changes from the stash will cause a merge conflict. You can resolve this in the same way as a usual merge conflict by editing the files, and then add the result to your next commit. (Note that when a pop causes a merge conflict, your changes will not be removed from the stash like normal so you will still have access to them if needed.)
::: {.infoboxred .exclamation}
::: infobox-header
Using the stash
:::
The git stash can technically hold many different sets of changes at once, but it is *not* good practice to store anything in the stash long-term. It is a temporary store and should only be used to quickly move changes around when needed.
:::
### I've worked on the wrong branch (and committed it)
If you've only realised that you're working on the wrong branch after committing your code, then you'll need to do two things. The first is to get the code onto the correct branch, and the second is to remove it from the wrong branch you committed it to.
If you **forgot to create a new branch**, you can create one now that includes the commits you want using
git branch <new_branch_name>
then roll back the current branch as described [here](#reset-revert).
If you **already created a branch but forgot to switch to it**, you'll need to move the commits to the correct branch. You can do this by checking out the correct branch and copying the commits to it using **cherry-pick**:
git checkout <correct_branch>
git cherry-pick <commit-hash>
where `<commit-hash>` is the commit you want to copy over. For multiple commits, you can copy them all over using
git cherry-pick <commit-hash-1>..<commit-hash-n>
where `<commit-hash-1>` is the earliest commit you want to copy and `<commit-hash-n>` is the most recent. Then check out the branch you accidentally committed them to and roll it back as described [here](#reset-revert).
## Other tips
### Log Customisation and Aliases
You can customise the log by adding extra arguments. For example, adding the `--oneline` argument the log is cut down to one line per commit.
``` sh
git log --oneline
```
There are a lot of possible arguments to add to the log. This example will show the latest commit on each branch, give a rough branching diagram and put the date in a specified format.
``` sh
git log --pretty=format:'%C(yellow)%h%Creset %an| %Cgreen%cd%Creset %s %C(cyan)%d' --graph --all --date=format:'%Y/%m/%d %H:%M'
```
All the possible arguments to add to `git log` are in the documentation [here](https://www.git-scm.com/docs/git-log).
Eventually you'll have too many arguments to sensibly type, so you can use an alias. An alias allows you to define a new command based on an old command. You define one like this:
``` sh
git config --global alias.<your_alias_name> = <your_command>
```
After this you can type
``` sh
git <your_alias_name>
```
to carry out the command.
For example, using the long, customised log from above we can define a new command, "hist".
``` sh
git config --global alias.hist = log --pretty=format:'%C(yellow)%h%Creset %an| %Cgreen%cd%Creset %s %C(cyan)%d' --graph --all --date=format:'%Y/%m/%d %H:%M'
```
Allowing us to type:
``` sh
git hist
```
to view a fancy version of the log, without having to type out a huge command!