UNPKG

12.3 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```js
171var commits = require('ggit').commits;
172commits.afterLastTag()
173 .then(function (list) { ... })
174```
175
176You can get commits after certain SHA
177
178```js
179var commits = require('ggit').commits;
180commits.after('439...')
181 .then(function (list) { ... })
182```
183
184
185### trackedFiles
186
187Returns all tracked source files in the given folder matching pattern.
188Both folder and pattern are optional.
189
190```js
191require('ggit')
192 .trackedFiles(__dirname, '*.js', options)
193 .then(function (list) {
194 console.log('javascript tracked in the current folder are');
195 console.log(list);
196 })
197 .done();
198```
199
200The `options` argument is optional, and is passed directly to the
201[glob](https://www.npmjs.com/package/glob) package that does file discovery.
202The only important option to use is `{ dot: true }` - if you want to find the
203filenames that start with `.`. For example to find ALL files in the repo call
204
205```js
206require('ggit')
207 .trackedFiles(__dirname, '**', { dot: true })
208// returns .gitignore, .travis.yml, index.js etc
209```
210
211
212### untrackedFiles
213
214Returns all untracked source files in the repo.
215
216```js
217require('ggit')
218 .untrackedFiles()
219 .then(function (list) {
220 // list is Array of strings, could be empty
221 console.log('untracked files are');
222 console.log(list);
223 })
224 .done();
225```
226
227
228### commitPerLine
229
230Returns an object where for each key (filename) there is a list of commits for each line.
231
232* list of filenames
233
234```js
235var perLine = require('ggit').commitPerLine;
236perLine(['foo.js', 'bar.js']).then(function (result) {
237 /*
238 {
239 'foo.js': [{
240 commit: '3c6b01eb3c96db1cbdf277904545107ef97cbb56',
241 author: 'Gleb Bahmutov',
242 committer: 'Gleb Bahmutov',
243 summary: 'cool commit',
244 filename: 'foo.js',
245 line: '// actual source line'
246 },
247 ...
248 }],
249 'bar.js': [...]
250 }
251 */
252});
253```
254
255
256### numstat
257
258Returns info for a specific commit - number of lines changed, deleted.
259Same as `$ git show --numstat <id>`.
260
261```js
262require('ggit')
263 .numstat('5d3ee3')
264 .then(function (result) {
265 /* result is
266 {
267 commit: <full commit SHA>,
268 author:
269 message:
270 date:
271 changes: {
272 'filename 1': {
273 filename: 'filename 1',
274 added: 10,
275 deleted: 3
276 },
277 ...
278 }
279 }
280 */
281 })
282 .done();
283```
284
285
286### lastCommitId
287
288Returns last commit id
289
290```js
291require('ggit')
292 .lastCommitId()
293 .then(function (str) {
294 // str is full SHA id string
295 })
296 .done();
297```
298
299You can pass options object as in `lastCommitId(options)` where
300
301* **file** - save id into the JSON file with the given `file` name.
302
303
304### branchName
305
306Resolves with the current branch name
307
308```js
309require('ggit').branchName()
310 .then(function (name) {
311 // name = "master" or whatever
312 });
313```
314
315
316### changedFiles
317
318Returns list of modified files
319
320```javascript
321var changedFiles = require('ggit').changedFiles;
322changedFiles()
323 .then(function (files) {})
324 .catch(function (error) {});
325```
326
327The object `files` groups filenames by modification property
328
329```js
330{
331 A: [...], // list of added files
332 C: [...], // list of copied files
333 M: [...], // list of modified files
334 D: [...] // list of deleted files
335}
336// each item in the list is
337{
338 diff: 'A' // or C, M, D
339 name: 'src/something.js' // relative to the repo root
340 filename: 'full path',
341 before: 'file contents', // if available (for example M, D)
342 after: 'file contents' // if available (for A, M)
343}
344```
345
346This is a wrapper around two commands `git diff --name-status --diff-filter=ACMD`
347and `git status --porcelain`
348
349
350
351
352### changedFilesAfter
353
354Returns list of unique files modified / added / deleted after given commit.
355The commits are limited to specific branch (usually "master") to avoid mixing
356up multiple branches.
357
358```javascript
359var changedFilesAfter = require('ggit').changedFilesAfter;
360changedFilesAfter('a12f55f', 'master')
361 .then(console.log)
362 .catch(console.error);
363/*
364something like
365[ 'README.md',
366 'docs/commits.md',
367 'src/commits.js',
368 'src/get-one-line-log.js',
369 'package.json',
370 'src/last-commit-id.js' ]
371*/
372```
373
374
375### fileContents
376
377Returns the contents of a file at some point
378
379* filename - full or partial filename (from the repo's root)
380* at (optional) - checkpoint, HEAD by default
381
382```javascript
383var fileContents = require('ggit').fileContents;
384fileContents(filename).then(function (text) { ... });
385```
386
387Same as `git show <at>:<name>`
388
389
390
391### commitMessage
392
393Returns the contents of the Git current commit message,
394usually for validation before the commit.
395
396```js
397require('ggit').commitMessage()
398 .then(function (text) {
399 // do something with the message
400 },
401 function () {
402 // file not found
403 });
404```
405
406
407### getGitFolder
408
409Returns the root folder, equivalent to command
410line `git rev-parse --show-toplevel`
411
412```javascript
413require('ggit').getGitFolder()
414 .then(folder => {
415 ...
416 })
417```
418
419
420### tags
421
422> Requires `git` >= 2.0
423
424Returns list of tags in the given folder, including commit ids.
425
426```js
427var tags = require('ggit').tags;
428tags().then(function (list) {
429 /*
430 each object in list is like
431 {
432 "commit": "7756b5609c5aae651f267fa3fc00763bcd276bf6",
433 "tag": "v1.3.0"
434 }
435 */
436})
437```
438You can return just tags that start with "v" by passing
439`true` to `tags`.
440
441```js
442tags(true).then(function (list) {...})
443```
444
445Oldest tag is returns as first object, latest tag is the
446last object in the list.
447
448If you have older `git` (like Travis does), it will automatically try to
449grab all the tags and sort them using
450[semantic sort](https://github.com/semver/node-semver#comparison)
451
452### branchTags
453
454> Requires `git` >= 2.7
455
456Similar to `tags`, `branchTags` returns tags in the given folder,
457but only those tags accessible from the current branch. Any tags
458in the repository that point to a commit on another branch will
459not be returned by `branchTags`.
460
461```js
462var branchTags = require('ggit').branchTags;
463branchTags().then(function (list) {
464 /*
465 each object in list is like
466 {
467 "commit": "7756b5609c5aae651f267fa3fc00763bcd276bf6",
468 "tag": "v1.3.0"
469 }
470 */
471})
472```
473You can return just tags that start with "v" by passing
474`true` to `branchTags`.
475
476```js
477branchTags(true).then(function (list) {...})
478```
479
480Oldest tag is returned as first object, latest tag is the
481last object in the list.
482
483
484### fetchTags
485
486Fetches remote tags from origin.
487
488```js
489var fetchTags = require('ggit').fetchTags;
490fetchTags().then(function () {
491 // should be same as running command
492 // git pull origin --tags
493})
494```
495
496You can pass the branch name, by default will fetch
497from master
498
499```js
500fetchTags('development')
501```
502
503
504
505
506
507## Development
508
509Edit source, run unit tests, run end to end tests and push the code
510back to Github. The NPM publishing happens automatically using
511[semantic release](https://github.com/semantic-release/semantic-release)
512
513```sh
514npm test
515npm run commit
516git push
517```
518
519To debug problems, run the command with `DEBUG=ggit` environment variable enabled
520to see verbose logging.
521
522### Unit tests
523
524Some of the unit tests rely on extracting private functions from modules
525using [scope magic with `describe-it`](https://github.com/bahmutov/describe-it),
526which requires Node 4.2.2 and might not work with later Node versions.
527
528### Related projects
529
530* [npm-utils](https://github.com/bahmutov/npm-utils) - small utils for working
531with NPM commands.
532
533
534
535### Small print
536
537Author: Gleb Bahmutov &copy; 2015
538
539* [@bahmutov](https://twitter.com/bahmutov)
540* [glebbahmutov.com](http://glebbahmutov.com)
541* [blog](http://glebbahmutov.com/blog/)
542
543License: [MIT](LICENSE) - do anything with the code, but don't blame uTest if it does not work.
544
545Spread the word: tweet, star on github, etc.
546
547Support: if you find any problems with this module, email / tweet / open
548[issue on Github](https://github.com/bahmutov/ggit/issues)
549
550