UNPKG

11.6 kBMarkdownView Raw
1# ggit
2
3> Local promise-returning git command wrappers
4
5[![NPM][ggit-icon] ][ggit-url]
6
7[![Build status][ggit-ci-image] ][ggit-ci-url]
8[![dependencies][ggit-dependencies-image] ][ggit-dependencies-url]
9[![devdependencies][ggit-devdependencies-image] ][ggit-devdependencies-url]
10[![semantic-release][semantic-image] ][semantic-url]
11[![manpm](https://img.shields.io/badge/manpm-%E2%9C%93-3399ff.svg)](https://github.com/bahmutov/manpm)
12
13[ggit-icon]: https://nodei.co/npm/ggit.svg?downloads=true
14[ggit-url]: https://npmjs.org/package/ggit
15[ggit-ci-image]: https://travis-ci.org/bahmutov/ggit.svg?branch=master
16[ggit-ci-url]: https://travis-ci.org/bahmutov/ggit
17[ggit-dependencies-image]: https://david-dm.org/bahmutov/ggit.svg
18[ggit-dependencies-url]: https://david-dm.org/bahmutov/ggit
19[ggit-devdependencies-image]: https://david-dm.org/bahmutov/ggit/dev-status.svg
20[ggit-devdependencies-url]: https://david-dm.org/bahmutov/ggit#info=devDependencies
21[semantic-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
22[semantic-url]: https://github.com/semantic-release/semantic-release
23
24
25
26## Stand alone tool
27
28You can install and run this tool as a stand alone CLI application.
29
30 npm install -g ggit
31 ggit --help
32 # get last commit id in the current folder, save into json file
33 ggit last -f build.json
34
35## API
36
37### cloneRepo
38
39```javascript
40var clone = require('ggit').cloneRepo;
41clone({
42 url: 'git@github.com:bahmutov/test-next-updater.git',
43 folder: 'folder to create, should not exist yet'
44}).then(function () {
45 console.log('cloned repo to destination folder');
46});
47```
48
49### exec
50
51```javascript
52var exec = require('ggit').exec;
53var cmd = 'rm -rf folder';
54var verbose = true;
55exec(cmd, verbose).then(function () {
56 console.log('removed folder');
57});
58```
59
60### blame
61
62Finds last person who has touched specific line in a file
63
64* filename - full or partial filename (from the repo's root)
65* lineNumber - starts with 1
66
67```javascript
68var blame = require('ggit').blame;
69blame(filename, lineNumber).then(function (info) {
70 /*
71 info is object with fields like
72 { commit: '6e65f8ec5ed63cac92ed130b1246d9c23223c04e',
73 author: 'Gleb Bahmutov',
74 committer: 'Gleb Bahmutov',
75 summary: 'adding blame feature',
76 filename: 'test/blame.js',
77 line: 'var blame = require(\'../index\').blame;' }
78 */
79});
80```
81
82Equivalent to porcelain git output: see [git-blame](http://git-scm.com/docs/git-blame)
83
84
85
86### isTracked
87
88Returns `true` if given path is tracked in the repo.
89
90* path
91
92```javascript
93var isTracked = require('ggit').isTracked;
94isTracked(filename).then(function (result) {
95 // result is true or false
96});
97```
98
99
100### hasChanges
101
102Returns `true` if there are local uncommitted stages
103
104```javascript
105var changed = require('ggit').hasChanges;
106changed().then(function (result) {
107 // result is true or false
108});
109```
110
111
112### commit
113
114Commit any changes with a given message. Second argument is optional and will
115be added after a blank line to the short main message.
116
117```js
118var commit = require('ggit').commit;
119commit('added foo', 'long text').then(function () {
120 // after commit
121});
122```
123
124You can pass the entire message if wanted as first argument
125
126```js
127var fullMessage = 'first line\n\nbody of message\n';
128commit(fullMessage).then(...);
129```
130
131
132### push
133
134Push commits to the remote
135
136```javascript
137var psuh = require('ggit').psuh;
138psuh().then(function () {
139 // after the push
140});
141```
142
143
144### commits
145
146Returns list of commits in the given folder as a list or object
147
148```js
149// commits.all - gets all commits
150var commits = require('ggit').commits;
151commits.all(gitRepoFolder)
152 .then(R.take(2))
153 .then(console.table)
154 .done();
155// commits.byId - transforms list of commits into object
156// where keys = ids, values = messages
157// For example to get an object with 2 commit ids as keys
158commits.all(gitRepoFolder)
159 .then(R.take(2))
160 .then(commits.byId)
161 .then(console.log)
162 .done();
163```
164
165Each object has at least 'id', 'message' and (maybe empty) 'body' properties.
166
167You can also return just the commits starting from the last version tag
168(which usually starts with 'v'). This is useful for semantic release code.
169
170```sh
171var commits = require('ggit').commits;
172commits.afterLastTag()
173 .then(function (list) { ... })
174```
175
176
177### trackedFiles
178
179Returns all tracked source files in the given folder matching pattern.
180Both folder and pattern are optional.
181
182```js
183require('ggit')
184 .trackedFiles(__dirname, '*.js', options)
185 .then(function (list) {
186 console.log('javascript tracked in the current folder are');
187 console.log(list);
188 })
189 .done();
190```
191
192The `options` argument is optional, and is passed directly to the
193[glob](https://www.npmjs.com/package/glob) package that does file discovery.
194The only important option to use is `{ dot: true }` - if you want to find the
195filenames that start with `.`. For example to find ALL files in the repo call
196
197```js
198require('ggit')
199 .trackedFiles(__dirname, '**', { dot: true })
200// returns .gitignore, .travis.yml, index.js etc
201```
202
203
204### untrackedFiles
205
206Returns all untracked source files in the repo.
207
208```js
209require('ggit')
210 .untrackedFiles()
211 .then(function (list) {
212 // list is Array of strings, could be empty
213 console.log('untracked files are');
214 console.log(list);
215 })
216 .done();
217```
218
219
220### commitPerLine
221
222Returns an object where for each key (filename) there is a list of commits for each line.
223
224* list of filenames
225
226```js
227var perLine = require('ggit').commitPerLine;
228perLine(['foo.js', 'bar.js']).then(function (result) {
229 /*
230 {
231 'foo.js': [{
232 commit: '3c6b01eb3c96db1cbdf277904545107ef97cbb56',
233 author: 'Gleb Bahmutov',
234 committer: 'Gleb Bahmutov',
235 summary: 'cool commit',
236 filename: 'foo.js',
237 line: '// actual source line'
238 },
239 ...
240 }],
241 'bar.js': [...]
242 }
243 */
244});
245```
246
247
248### numstat
249
250Returns info for a specific commit - number of lines changed, deleted.
251Same as `$ git show --numstat <id>`.
252
253```js
254require('ggit')
255 .numstat('5d3ee3')
256 .then(function (result) {
257 /* result is
258 {
259 commit: <full commit SHA>,
260 author:
261 message:
262 date:
263 changes: {
264 'filename 1': {
265 filename: 'filename 1',
266 added: 10,
267 deleted: 3
268 },
269 ...
270 }
271 }
272 */
273 })
274 .done();
275```
276
277
278### lastCommitId
279
280Returns last commit id
281
282```js
283require('ggit')
284 .lastCommitId()
285 .then(function (str) {
286 // str is full SHA id string
287 })
288 .done();
289```
290
291You can pass options object as in `lastCommitId(options)` where
292
293* **file** - save id into the JSON file with the given `file` name.
294
295
296### branchName
297
298Resolves with the current branch name
299
300```js
301require('ggit').branchName()
302 .then(function (name) {
303 // name = "master" or whatever
304 });
305```
306
307
308### changed-files
309
310Returns list of modified files
311
312```javascript
313var changedFiles = require('ggit').changedFiles;
314changedFiles()
315 .then(function (files) {})
316 .catch(function (error) {});
317```
318
319The object `files` groups filenames by modification property
320
321```js
322{
323 A: [...], // list of added files
324 C: [...], // list of copied files
325 M: [...], // list of modified files
326 D: [...] // list of deleted files
327}
328// each item in the list is
329{
330 diff: 'A' // or C, M, D
331 name: 'src/something.js' // relative to the repo root
332 filename: 'full path',
333 before: 'file contents', // if available (for example M, D)
334 after: 'file contents' // if available (for A, M)
335}
336```
337
338This is a wrapper around two commands `git diff --name-status --diff-filter=ACMD`
339and `git status --porcelain`
340
341
342
343
344### fileContents
345
346Returns the contents of a file at some point
347
348* filename - full or partial filename (from the repo's root)
349* at (optional) - checkpoint, HEAD by default
350
351```javascript
352var fileContents = require('ggit').fileContents;
353fileContents(filename).then(function (text) { ... });
354```
355
356Same as `git show <at>:<name>`
357
358
359
360### commitMessage
361
362Returns the contents of the Git current commit message,
363usually for validation before the commit.
364
365```js
366require('ggit').commitMessage()
367 .then(function (text) {
368 // do something with the message
369 },
370 function () {
371 // file not found
372 });
373```
374
375
376### getGitFolder
377
378Returns the root folder, equivalent to command
379line `git rev-parse --show-toplevel`
380
381```javascript
382require('ggit').getGitFolder()
383 .then(folder => {
384 ...
385 })
386```
387
388
389### tags
390
391> Requires `git` >= 2.0
392
393Returns list of tags in the given folder, including commit ids.
394
395```js
396var tags = require('ggit').tags;
397tags().then(function (list) {
398 /*
399 each object in list is like
400 {
401 "commit": "7756b5609c5aae651f267fa3fc00763bcd276bf6",
402 "tag": "v1.3.0"
403 }
404 */
405})
406```
407You can return just tags that start with "v" by passing
408`true` to `tags`.
409
410```js
411tags(true).then(function (list) {...})
412```
413
414Oldest tag is returns as first object, latest tag is the
415last object in the list.
416
417If you have older `git` (like Travis does), it will automatically try to
418grab all the tags and sort them using
419[semantic sort](https://github.com/semver/node-semver#comparison)
420
421### branchTags
422
423> Requires `git` >= 2.7
424
425Similar to `tags`, `branchTags` returns tags in the given folder,
426but only those tags accessible from the current branch. Any tags
427in the repository that point to a commit on another branch will
428not be returned by `branchTags`.
429
430```js
431var branchTags = require('ggit').branchTags;
432branchTags().then(function (list) {
433 /*
434 each object in list is like
435 {
436 "commit": "7756b5609c5aae651f267fa3fc00763bcd276bf6",
437 "tag": "v1.3.0"
438 }
439 */
440})
441```
442You can return just tags that start with "v" by passing
443`true` to `branchTags`.
444
445```js
446branchTags(true).then(function (list) {...})
447```
448
449Oldest tag is returned as first object, latest tag is the
450last object in the list.
451
452
453### fetchTags
454
455Fetches remote tags from origin.
456
457```js
458var fetchTags = require('ggit').fetchTags;
459fetchTags().then(function () {
460 // should be same as running command
461 // git pull origin --tags
462})
463```
464
465You can pass the branch name, by default will fetch
466from master
467
468```js
469fetchTags('development')
470```
471
472
473
474
475
476## Development
477
478Edit source, run unit tests, run end to end tests and push the code
479back to Github. The NPM publishing happens automatically using
480[semantic release](https://github.com/semantic-release/semantic-release)
481
482```sh
483npm test
484npm run commit
485git push
486```
487
488To debug problems, run the command with `DEBUG=ggit` environment variable enabled
489to see verbose logging.
490
491### Unit tests
492
493Some of the unit tests rely on extracting private functions from modules
494using [scope magic with `describe-it`](https://github.com/bahmutov/describe-it),
495which requires Node 4.2.2 and might not work with later Node versions.
496
497### Related projects
498
499* [npm-utils](https://github.com/bahmutov/npm-utils) - small utils for working
500with NPM commands.
501
502
503
504### Small print
505
506Author: Gleb Bahmutov &copy; 2015
507
508* [@bahmutov](https://twitter.com/bahmutov)
509* [glebbahmutov.com](http://glebbahmutov.com)
510* [blog](http://glebbahmutov.com/blog/)
511
512License: [MIT](LICENSE) - do anything with the code, but don't blame uTest if it does not work.
513
514Spread the word: tweet, star on github, etc.
515
516Support: if you find any problems with this module, email / tweet / open
517[issue on Github](https://github.com/bahmutov/ggit/issues)
518
519