aboutsummaryrefslogtreecommitdiff
path: root/vim/bundle/vim-gitgutter/README.mkd
blob: 6fc92aeeeb28e0078391642caf4542049436665d (plain)
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
## vim-gitgutter

A Vim plugin which shows a git diff in the 'gutter' (sign column).  It shows whether each line has been added, modified, and where lines have been removed.  You can also stage and undo individual hunks.

Features:

* Shows signs for added, modified, and removed lines.
* Runs the diffs asynchronously in terminal Vim/MacVim (7.4.1826+), gVim (7.4.1850+), MacVim GUI (7.4.1832+), and NeoVim.
* Ensures signs are always as up to date as possible (but without running more than necessary).
* Quick jumping between blocks of changed lines ("hunks").
* Stage/undo/preview individual hunks.
* Provides a hunk text object.
* Diffs against index (default) or any commit.
* Handles line endings correctly, even with repos that do CRLF conversion.
* Optional line highlighting.
* Fully customisable (signs, sign column, line highlights, mappings, extra git-diff arguments, etc).
* Can be toggled on/off.
* Preserves signs from other plugins.
* Easy to integrate diff stats into status line; built-in integration with [vim-airline](https://github.com/bling/vim-airline/).
* Works with fish shell (in addition to the usual shells).

Constraints:

* Supports git only.

If you work with other version control systems, I recommend [vim-signify](https://github.com/mhinz/vim-signify).


### Screenshot

![screenshot](https://raw.github.com/airblade/vim-gitgutter/master/screenshot.png)

In the screenshot above you can see:

* Line 15 has been modified.
* Lines 21-24 are new.
* A line or lines were removed between lines 25 and 26.


### Installation

Before installation, please check your Vim supports signs by running `:echo has('signs')`.  `1` means you're all set; `0` means you need to install a Vim with signs support.  If you're compiling Vim yourself you need the 'big' or 'huge' feature set.  [MacVim][] supports signs.

You install vim-gitgutter like any other vim plugin.

##### Pathogen

```
cd ~/.vim/bundle
git clone git://github.com/airblade/vim-gitgutter.git
```

##### Voom

Edit your plugin manifest (`voom edit`) and add:

```
airblade/vim-gitgutter
```

##### VimPlug

Place this in your .vimrc:

```viml
Plug 'airblade/vim-gitgutter'
```

Then run the following in Vim:

```
:source %
:PlugInstall
```

##### NeoBundle

Place this in your .vimrc:

```viml
NeoBundle 'airblade/vim-gitgutter'
```

Then run the following in Vim:

```
:source %
:NeoBundleInstall
```

##### No plugin manager

Copy vim-gitgutter's subdirectories into your vim configuration directory:

```
cd /tmp && git clone git://github.com/airblade/vim-gitgutter.git
cp -r vim-gitgutter/* ~/.vim/
```

See `:help add-global-plugin`.


If you are on Windows you may find the command prompt pops up briefly every time vim-gitgutter runs.  You can avoid this by installing both [vim-misc](https://github.com/xolox/vim-misc) and [vim-shell](https://github.com/xolox/vim-shell).  If you have those two plugins but don't want vim-gitgutter to use them, you can opt out with `let g:gitgutter_avoid_cmd_prompt_on_windows = 0` in your `~/.vimrc`.


### Getting started

When you make a change to a file tracked by git, the diff markers should appear automatically.  The delay is governed by vim's `updatetime` option; the default value is 4 seconds but I suggest reducing it to around 250ms (add `set updatetime=250` to your vimrc).

You can jump between hunks with `[c` and `]c`.  You can preview, stage, and undo hunks with `<leader>hp`, `<leader>hs`, and `<leader>hu` respectively.

You cannot currently unstage a staged hunk.


#### Activation

You can explicitly turn vim-gitgutter off and on (defaults to on):

* turn off with `:GitGutterDisable`
* turn on with `:GitGutterEnable`
* toggle with `:GitGutterToggle`.

You can turn the signs on and off (defaults to on):

* turn on with `:GitGutterSignsEnable`
* turn off with `:GitGutterSignsDisable`
* toggle with `:GitGutterSignsToggle`.

And you can turn line highlighting on and off (defaults to off):

* turn on with `:GitGutterLineHighlightsEnable`
* turn off with `:GitGutterLineHighlightsDisable`
* toggle with `:GitGutterLineHighlightsToggle`.

Note that if you have line highlighting on and signs off, you will have an empty sign column – more accurately, a sign column with invisible signs.  This is because line highlighting requires signs and Vim always shows the sign column even if the signs are invisible.

If you switch off both line highlighting and signs, you won't see the sign column.  That is unless you have set `let g:gitgutter_sign_column_always = 1` so it's always there.

To keep your Vim snappy, vim-gitgutter will suppress itself when a file has more than 500 changes.  As soon as the number of changes falls below the limit vim-gitgutter will show the signs again.  You can configure the threshold with:

```viml
let g:gitgutter_max_signs = 500  " default value
```

#### Hunks

You can jump between hunks:

* jump to next hunk (change): `]c`
* jump to previous hunk (change): `[c`.

Both of those take a preceding count.

To set your own mappings for these, for example `]h` and `[h`:

```viml
nmap ]h <Plug>GitGutterNextHunk
nmap [h <Plug>GitGutterPrevHunk
```

You can stage or undo an individual hunk when your cursor is in it:

* stage the hunk with `<Leader>hs` or
* undo it with `<Leader>hu`.

See the FAQ if you want to unstage staged changes.

The `.` command will work with both these if you install [repeat.vim](https://github.com/tpope/vim-repeat).

To set your own mappings for these, for example if you prefer the mnemonics hunk-add and hunk-revert:

```viml
nmap <Leader>ha <Plug>GitGutterStageHunk
nmap <Leader>hr <Plug>GitGutterUndoHunk
```

And you can preview a hunk's changes with `<Leader>hp`.  You can of course change this mapping, e.g:

```viml
nmap <Leader>hv <Plug>GitGutterPreviewHunk
```

A hunk text object is provided which works in visual and operator-pending modes.

- `ic` operates on all lines in the current hunk.
- `ac` operates on all lines in the current hunk and any trailing empty lines.

To re-map these, for example to `ih` and `ah`:

```viml
omap ih <Plug>GitGutterTextObjectInnerPending
omap ah <Plug>GitGutterTextObjectOuterPending
xmap ih <Plug>GitGutterTextObjectInnerVisual
xmap ah <Plug>GitGutterTextObjectOuterVisual
```

If you don't want vim-gitgutter to set up any mappings at all, use this:

```viml
let g:gitgutter_map_keys = 0
```

Finally, you can force vim-gitgutter to update its signs across all visible buffers with `:GitGutterAll`.

See the customisation section below for how to change the defaults.


### When are the signs updated?

By default the signs are updated as follows:

| Event                     | Reason for update                    | Configuration          |
|---------------------------|--------------------------------------|------------------------|
| Stop typing               | So the signs are real time           | `g:gitgutter_realtime` |
| Switch buffer             | To notice change to git index        | `g:gitgutter_eager`    |
| Switch tab                | To notice change to git index        | `g:gitgutter_eager`    |
| Focus the GUI             | To notice change to git index        | `g:gitgutter_eager` (not gVim on Windows) |
| Read a file into a buffer | To display initial signs             | [always]               |
| Save a buffer             | So non-realtime signs are up to date | [always]               |
| Change a file outside Vim | To notice `git stash`                | [always]               |

The length of time Vim waits after you stop typing before it triggers the plugin is governed by the setting `updatetime`.  This defaults to `4000` milliseconds which is rather too long.  I recommend around `250` milliseconds but it depends on your system and your preferences.  Note that in terminal Vim pre-7.4.427 an `updatetime` of less than approximately `1000` milliseconds can lead to random highlighting glitches; the lower the `updatetime`, the more glitches.

If you experience a lag, you can trade speed for accuracy:

```viml
let g:gitgutter_realtime = 0
let g:gitgutter_eager = 0
```

Note the realtime updating requires Vim 7.3.105 or higher.


### Customisation

You can customise:

* The sign column's colours
* Whether or not the sign column is shown when there aren't any signs (defaults to no)
* The signs' colours and symbols
* Line highlights
* The base of the diff
* Extra arguments for `git diff`
* Key mappings
* Whether or not vim-gitgutter is on initially (defaults to on)
* Whether or not signs are shown (defaults to yes)
* Whether or not line highlighting is on initially (defaults to off)
* Whether or not vim-gitgutter runs in "realtime" (defaults to yes)
* Whether or not vim-gitgutter runs eagerly (defaults to yes)
* Whether or not vim-gitgutter runs asynchronously (defaults to yes)

Please note that vim-gitgutter won't override any colours or highlights you've set in your colorscheme.


#### Sign column

By default vim-gitgutter will make the sign column look like the line number column.

To customise your sign column's background color, first tell vim-gitgutter to leave it alone:

```viml
let g:gitgutter_override_sign_column_highlight = 0
```

And then either update your colorscheme's `SignColumn` highlight group or set it in your vimrc:

```viml
highlight SignColumn ctermbg=whatever    " terminal Vim
highlight SignColumn guibg=whatever      " gVim/MacVim
```

By default the sign column will appear when there are signs to show and disappear when there aren't.  If you would always like the sign column to be there, add `let g:gitgutter_sign_column_always = 1` to your `~/.vimrc`.


#### Signs' colours and symbols

To customise the colours, set up the following highlight groups in your colorscheme or `~/.vimrc`:

```viml
GitGutterAdd          " an added line
GitGutterChange       " a changed line
GitGutterDelete       " at least one removed line
GitGutterChangeDelete " a changed line followed by at least one removed line
```

You can either set these with `highlight GitGutterAdd {key}={arg}...` or link them to existing highlight groups with, say, `highlight link GitGutterAdd DiffAdd`.

To customise the symbols, add the following to your `~/.vimrc`:

```viml
let g:gitgutter_sign_added = 'xx'
let g:gitgutter_sign_modified = 'yy'
let g:gitgutter_sign_removed = 'zz'
let g:gitgutter_sign_removed_first_line = '^^'
let g:gitgutter_sign_modified_removed = 'ww'
```


#### Line highlights

Similarly to the signs' colours, set up the following highlight groups in your colorscheme or `~/.vimrc`:

```viml
GitGutterAddLine          " default: links to DiffAdd
GitGutterChangeLine       " default: links to DiffChange
GitGutterDeleteLine       " default: links to DiffDelete
GitGutterChangeDeleteLine " default: links to GitGutterChangeLineDefault, i.e. DiffChange
```


#### The base of the diff

By default buffers are diffed against the index.  However you can diff against any commit by setting:

```viml
let g:gitgutter_diff_base = '<commit SHA>'
```


#### Extra arguments for `git diff`

If you want to pass extra arguments to `git diff`, for example to ignore whitespace, do so like this:

```viml
let g:gitgutter_diff_args = '-w'
```

#### Key mappings

To disable all key mappings:

```viml
let g:gitgutter_map_keys = 0
```

See above for configuring maps for hunk-jumping and staging/undoing.


#### Use a custom `grep` command

If you use an alternative to grep, or your grep does not support the `color` flag, you can tell vim-gitgutter to use it here. It only needs to support extended POSIX regex.

```viml
" Default:
let g:gitgutter_grep_command = 'grep --color=never -e'
```

#### To turn off vim-gitgutter by default

Add `let g:gitgutter_enabled = 0` to your `~/.vimrc`.


#### To turn off signs by default

Add `let g:gitgutter_signs = 0` to your `~/.vimrc`.


#### To turn on line highlighting by default

Add `let g:gitgutter_highlight_lines = 1` to your `~/.vimrc`.


#### To turn off asynchronous updates

By default diffs are run asynchronously.  To run diffs synchronously instead:

```viml
let g:gitgutter_async = 0
```


### Extensions

#### Operate on every line in a hunk

You can map an operator to do whatever you want to every line in a hunk.

Let's say, for example, you want to remove trailing whitespace.

```viml
function! CleanUp(...)
  if a:0  " opfunc
    let [first, last] = [line("'["), line("']")]
  else
    let [first, last] = [line("'<"), line("'>")]
  endif
  for lnum in range(first, last)
    let line = getline(lnum)

    " clean up the text, e.g.:
    let line = substitute(line, '\s\+$', '', '')

    call setline(lnum, line)
  endfor
endfunction

nmap <silent> <Leader>x :set opfunc=CleanUp<CR>g@
```

Then place your cursor in a hunk and type `\xic` (assuming a leader of `\`).

Alternatively you could place your cursor in a hunk, type `vic` to select it, then `:call CleanUp()`.


#### Operate on every changed line in a file

You can write a command to do whatever you want to every changed line in a file.

```viml
function! GlobalChangedLines(ex_cmd)
  for hunk in GitGutterGetHunks()
    for lnum in range(hunk[2], hunk[2]+hunk[3]-1)
      let cursor = getcurpos()
      silent! execute lnum.a:ex_cmd
      call setpos('.', cursor)
    endfor
  endfor
endfunction

command -nargs=1 Glines call GlobalChangedLines(<q-args>)
```

Let's say, for example, you want to remove trailing whitespace from all changed lines:

```viml
:Glines s/\s\+$//
```


### FAQ

> Why can't I unstage staged changes?

Unstaging staged hunks is feasible but not quite as easy as it sounds.  There are three relevant versions of a file at any one time:

1. The version at HEAD in the repo.
2. The version staged in the index.
3. The version in the working tree, in your vim buffer.

`git-diff` without arguments shows you how 3 and 2 differ; this is what vim-gitgutter shows too.

`git-diff --staged` shows you how 2 and 1 differ.

Let's say your are looking at a file in vim which has some unstaged changes.  Now you stage a hunk, either via vim-gitgutter or another means.  The hunk is no longer marked in vim-gitgutter because it is the same in 3 and 2.

Now you want to unstage that hunk.  To see it, you need the difference between 2 and 1.  For vim-gitgutter to shows those differences, it would need to show you 2 instead of 3 in your vim buffer.  But 2 is virtual so vim-gitgutter would need to handle it without touching 3.

I intend to implement this but I can't commit to any deadline.

> Why are the colours in the sign column weird?

Your colorscheme is configuring the `SignColumn` highlight group weirdly.  Please see the section above on customising the sign column.

> There's a noticeable lag when vim-gitter runs; how can I avoid it?

By default vim-gitgutter runs often so the signs are as accurate as possible.  The delay is governed by `updatetime`; see [above](#when-are-the-signs-updated) for more information.

If you don't want realtime updates and would like to trade a little accuracy for speed, add this to your `~/.vimrc`:

```viml
let g:gitgutter_realtime = 0
let g:gitgutter_eager = 0
```

> What happens if I also use another plugin which uses signs (e.g. Syntastic)?

Vim only allows one sign per line.  Before adding a sign to a line, vim-gitgutter checks whether a sign has already been added by somebody else.  If so it doesn't do anything.  In other words vim-gitgutter won't overwrite another plugin's signs.  It also won't remove another plugin's signs.

> Why aren't any signs showing at all?

Here are some things you can check:

* `:echo system("git --version")` succeeds.
* Your git config is compatible with the version of git returned by the command above.
* Your Vim supports signs (`:echo has('signs')` should give `1`).
* Your file is being tracked by git and has unstaged changes.
* If your grep does not support the `color` flag, add `let g:gitgutter_grep_command = 'grep -e'` to your `~/.vimrc`.


### Shameless Plug

If this plugin has helped you, or you'd like to learn more about Vim, why not check out this screencast I wrote for PeepCode:

* [Smash Into Vim][siv]

This was one of PeepCode's all-time top three bestsellers and is now available at Pluralsight.

You can read reviews on my [website][airblade].


### Intellectual Property

Copyright Andrew Stewart, AirBlade Software Ltd.  Released under the MIT licence.


  [pathogen]: https://github.com/tpope/vim-pathogen
  [siv]: http://pluralsight.com/training/Courses/TableOfContents/smash-into-vim
  [airblade]: http://airbladesoftware.com/peepcode-vim
  [macvim]: http://code.google.com/p/macvim/