UNPKG

39.9 kBMarkdownView Raw
1# Simple Git
2[![NPM version](https://img.shields.io/npm/v/simple-git.svg)](https://www.npmjs.com/package/simple-git)
3 [![Build Status](https://travis-ci.org/steveukx/git-js.svg?branch=master)](https://travis-ci.org/steveukx/git-js)
4
5A lightweight interface for running `git` commands in any [node.js](https://nodejs.org) application.
6
7# Installation
8
9Use your favourite package manager:
10
11- [npm](https://npmjs.org): `npm install simple-git`
12- [yarn](https://yarnpkg.com/): `yarn add simple-git`
13
14# System Dependencies
15
16Requires [git](https://git-scm.com/downloads) to be installed and that it can be called using the command `git`.
17
18# Usage
19
20Include into your JavaScript app using:
21
22```js
23// require the library, main export is a function
24const simpleGit = require('simple-git');
25const git = simpleGit();
26```
27
28Include in a TypeScript app using:
29
30```typescript
31// Import `SimpleGit` types and the default function exported from `simple-git`
32import simpleGit, {SimpleGit} from 'simple-git';
33const git: SimpleGit = simpleGit();
34
35// prior to v2.6.0 required importing from `simple-git/promise`
36// this import is still available but is now deprecated
37import gitP, {SimpleGit} from 'simple-git/promise';
38const git: SimpleGit = gitP();
39```
40
41## Configuration
42
43Configure each `simple-git` instance with a properties object passed to the main `simpleGit` function:
44
45```typescript
46import simpleGit, { SimpleGit, SimpleGitOptions } from 'simple-git';
47
48const options: Partial<SimpleGitOptions> = {
49 baseDir: process.cwd(),
50 binary: 'git',
51 maxConcurrentProcesses: 6,
52};
53
54// when setting all options in a single object
55const git: SimpleGit = simpleGit(options);
56
57// or split out the baseDir, supported for backward compatibility
58const git: SimpleGit = simpleGit('/some/path', { binary: 'git' });
59```
60
61The first argument can be either a string (representing the working directory for `git` commands to run in),
62`SimpleGitOptions` object or `undefined`, the second parameter is an optional `SimpleGitOptions` object.
63
64All configuration properties are optional, the default values are shown in the example above.
65
66## Per-command Configuration
67
68To prefix the commands run by `simple-git` with custom configuration not saved in the git config (ie: using the
69`-c` command) supply a `config` option to the instance builder:
70
71```typescript
72// configure the instance with a custom configuration property
73const git: SimpleGit = simpleGit('/some/path', { config: ['http.proxy=someproxy'] });
74
75// any command executed will be prefixed with this config
76// runs: git -c http.proxy=someproxy pull
77await git.pull();
78```
79
80## Configuring Plugins
81
82- [Completion Detection](./docs/PLUGIN-COMPLETION-DETECTION.md)
83 Customise how `simple-git` detects the end of a `git` process.
84
85- [Error Detection](./docs/PLUGIN-ERRORS.md)
86 Customise the detection of errors from the underlying `git` process.
87
88- [Progress Events](./docs/PLUGIN-PROGRESS-EVENTS.md)
89 Receive progress events as `git` works through long-running processes.
90
91- [Spawned Process Ownership](./docs/PLUGIN-SPAWN-OPTIONS.md)
92 Configure the system `uid` / `gid` to use for spawned `git` processes.
93
94- [Timeout](./docs/PLUGIN-TIMEOUT.md)
95 Automatically kill the wrapped `git` process after a rolling timeout.
96
97## Using task promises
98
99Each task in the API returns the `simpleGit` instance for chaining together multiple tasks, and each
100step in the chain is also a `Promise` that can be `await` ed in an `async` function or returned in a
101`Promise` chain.
102
103```javascript
104const simpleGit = require('simple-git');
105const git = simpleGit();
106
107// chain together tasks to await final result
108await git.init().addRemote('origin', '...remote.git');
109
110// or await each step individually
111await git.init();
112await git.addRemote('origin', '...remote.git')
113```
114
115## Catching errors in async code
116
117To catch errors in async code, either wrap the whole chain in a try/catch:
118
119```javascript
120const git = simpleGit()
121try {
122 await git.init();
123 await git.addRemote(name, repoUrl);
124}
125catch (e) { /* handle all errors here */ }
126```
127
128or catch individual steps to permit the main chain to carry on executing rather than
129jumping to the final `catch` on the first error:
130
131```javascript
132const git = simpleGit()
133try {
134 await git.init().catch(ignoreError);
135 await git.addRemote(name, repoUrl);
136}
137catch (e) { /* handle all errors here */ }
138
139function ignoreError () {}
140```
141
142## Using task callbacks
143
144In addition to returning promise method can be called with a trailing callback argument to handle the result of the task
145
146```javascript
147const simpleGit = require('simple-git');
148const git = simpleGit();
149git.init(onInit).addRemote('origin', 'git@github.com:steveukx/git-js.git', onRemoteAdd);
150
151function onInit (err, initResult) { }
152function onRemoteAdd (err, addRemoteResult) { }
153```
154
155If any of the steps in the chain result in an error, all pending steps will be cancelled, see the
156[parallel tasks]((#concurrent--parallel-requests)) section for more information on how to run tasks in parallel rather than in series .
157
158## Task Responses
159
160Whether using a trailing callback or a Promise, tasks either return the raw `string` or `Buffer` response from the
161`git` binary, or where possible a parsed interpretation of the response.
162
163For type details of the response for each of the tasks, please see the [TypeScript definitions](./typings/simple-git.d.ts).
164
165
166# API
167
168| API | What it does |
169|-----|--------------|
170| `.add([fileA, ...], handlerFn)` | adds one or more files to be under source control |
171| `.addAnnotatedTag(tagName, tagMessage, handlerFn)` | adds an annotated tag to the head of the current branch |
172| `.addTag(name, handlerFn)` | adds a lightweight tag to the head of the current branch |
173| `.catFile(options[, handlerFn])` | generate `cat-file` detail, `options` should be an array of strings as supported arguments to the [cat-file](https://git-scm.com/docs/git-cat-file) command |
174| `.checkIgnore([filepath, ...], handlerFn)` | checks if filepath excluded by .gitignore rules |
175| `.clearQueue()` | immediately clears the queue of pending tasks (note: any command currently in progress will still call its completion callback) |
176| `.commit(message, handlerFn)` | commits changes in the current working directory with the supplied message where the message can be either a single string or array of strings to be passed as separate arguments (the `git` command line interface converts these to be separated by double line breaks) |
177| `.commit(message, [fileA, ...], options, handlerFn)` | commits changes on the named files with the supplied message, when supplied, the optional options object can contain any other parameters to pass to the commit command, setting the value of the property to be a string will add `name=value` to the command string, setting any other type of value will result in just the key from the object being passed (ie: just `name`), an example of setting the author is below |
178| `.customBinary(gitPath)` | sets the command to use to reference git, allows for using a git binary not available on the path environment variable |
179| `.diff(options, handlerFn)` | get the diff of the current repo compared to the last commit with a set of options supplied as a string |
180| `.diff(handlerFn)` | get the diff for all file in the current repo compared to the last commit |
181| `.diffSummary(handlerFn)` | gets a summary of the diff for files in the repo, uses the `git diff --stat` format to calculate changes. Handler is called with a nullable error object and an instance of the [DiffSummary](src/lib/responses/DiffSummary.js) |
182| `.diffSummary(options, handlerFn)` | includes options in the call to `diff --stat options` and returns a [DiffSummary](src/lib/responses/DiffSummary.js) |
183| `.env(name, value)` | Set environment variables to be passed to the spawned child processes, [see usage in detail below](#environment-variables). |
184| `.exec(handlerFn)` | calls a simple function in the current step |
185| `.fetch([options, ] handlerFn)` | update the local working copy database with changes from the default remote repo and branch, when supplied the options argument can be a standard [options object](#how-to-specify-options) either an array of string commands as supported by the [git fetch](https://git-scm.com/docs/git-fetch). |
186| `.fetch(remote, branch, handlerFn)` | update the local working copy database with changes from a remote repo |
187| `.fetch(handlerFn)` | update the local working copy database with changes from the default remote repo and branch |
188| `.outputHandler(handlerFn)` | attaches a handler that will be called with the name of the command being run and the `stdout` and `stderr` [readable streams](https://nodejs.org/api/stream.html#stream_class_stream_readable) created by the [child process](https://nodejs.org/api/child_process.html#child_process_class_childprocess) running that command |
189| `.raw(args[, handlerFn])` | Execute any arbitrary array of commands supported by the underlying git binary. When the git process returns a non-zero signal on exit and it printed something to `stderr`, the commmand will be treated as an error, otherwise treated as a success. |
190| `.rebase([options,] handlerFn)` | Rebases the repo, `options` should be supplied as an array of string parameters supported by the [git rebase](https://git-scm.com/docs/git-rebase) command, or an object of options (see details below for option formats). |
191| `.revert(commit [, options [, handlerFn]])` | reverts one or more commits in the working copy. The commit can be any regular commit-ish value (hash, name or offset such as `HEAD~2`) or a range of commits (eg: `master~5..master~2`). When supplied the [options](#how-to-specify-options) argument contain any options accepted by [git-revert](https://git-scm.com/docs/git-revert). |
192| `.rm([fileA, ...], handlerFn)` | removes any number of files from source control |
193| `.rmKeepLocal([fileA, ...], handlerFn)` | removes files from source control but leaves them on disk |
194| `.stash([options, ][ handlerFn])` | Stash the working directory, optional first argument can be an array of string arguments or [options](#how-to-specify-options) object to pass to the [git stash](https://git-scm.com/docs/git-stash) command. |
195| `.stashList([options, ][handlerFn])` | Retrieves the stash list, optional first argument can be an object specifying `options.splitter` to override the default value of `;;;;`, alternatively options can be a set of arguments as supported by the `git stash list` command. |
196| `.tag(args[], handlerFn)` | Runs any supported [git tag](https://git-scm.com/docs/git-tag) commands with arguments passed as an array of strings . |
197| `.tags([options, ] handlerFn)` | list all tags, use the optional [options](#how-to-specify-options) object to set any options allows by the [git tag](https://git-scm.com/docs/git-tag) command. Tags will be sorted by semantic version number by default, for git versions 2.7 and above, use the `--sort` option to set a custom sort. |
198| `.show([options], handlerFn)` | Show various types of objects, for example the file content at a certain commit. `options` is the single value string or array of string commands you want to run |
199
200## git apply
201
202- `.applyPatch(patch, [options])` applies a single string patch (as generated by `git diff`), optionally configured with the supplied [options](#how-to-specify-options) to set any arguments supported by the [apply](https://git-scm.com/docs/git-apply) command. Returns the unmodified string response from `stdout` of the `git` binary.
203- `.applyPatch(patches, [options])` applies an array of string patches (as generated by `git diff`), optionally configured with the supplied [options](#how-to-specify-options) to set any arguments supported by the [apply](https://git-scm.com/docs/git-apply) command. Returns the unmodified string response from `stdout` of the `git` binary.
204
205## git branch
206
207- `.branch([options])` uses the supplied [options](#how-to-specify-options) to run any arguments supported by the [branch](https://git-scm.com/docs/git-branch) command. Either returns a [BranchSummaryResult](src/lib/responses/BranchSummary.ts) instance when listing branches, or a [BranchSingleDeleteResult](typings/response.d.ts) type object when the options included `-d`, `-D` or `--delete` which cause it to delete a named branch rather than list existing branches.
208- `.branchLocal()` gets a list of local branches as a [BranchSummaryResult](src/lib/responses/BranchSummary.ts) instance
209- `.deleteLocalBranch(branchName)` deletes a local branch - treats a failed attempt as an error
210- `.deleteLocalBranch(branchName, forceDelete)` deletes a local branch, optionally explicitly setting forceDelete to true - treats a failed attempt as an error
211- `.deleteLocalBranches(branchNames)` deletes multiple local branches
212- `.deleteLocalBranches(branchNames, forceDelete)` deletes multiple local branches, optionally explicitly setting forceDelete to true
213
214## git clean
215
216- `.clean(mode)` clean the working tree. Mode should be "n" - dry run or "f" - force
217- `.clean(cleanSwitches [,options])` set `cleanSwitches` to a string containing any number of the supported single character options, optionally with a standard [options](#how-to-specify-options) object
218
219## git checkout
220
221- `.checkout(checkoutWhat [, options])` - checks out the supplied tag, revision or branch when supplied as a string,
222 additional arguments supported by [git checkout](https://git-scm.com/docs/git-checkout) can be supplied as an
223 [options](#how-to-specify-options) object/array.
224
225- `.checkout(options)` - uses the checks out the supplied [options](#how-to-specify-options) object/array to check out.
226
227- `.checkoutBranch(branchName, startPoint)` - checks out a new branch from the supplied start point.
228
229- `.checkoutLocalBranch(branchName)` - checks out a new local branch
230
231## git clone
232
233- `.clone(repoPath, [localPath, [options]])` clone a remote repo at `repoPath` to a local directory at `localPath`, optionally with a standard [options](#how-to-specify-options) object of additional arguments to include between `git clone` and the trailing `repo local` arguments
234- `.clone(repoPath, [options])` clone a remote repo at `repoPath` to a directory in the current working directory with the same name as the repo
235
236- `mirror(repoPath, [localPath, [options]])` behaves the same as the `.clone` interface with the [`--mirror` flag](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---mirror) enabled.
237
238
239## git config
240
241- `.addConfig(key, value, append = false, scope = 'local')` add a local configuration property, when `append` is set to
242 `true` the configuration setting is appended to rather than overwritten in the local config. Use the `scope` argument
243 to pick where to save the new configuration setting (use the exported `GitConfigScope` enum, or equivalent string
244 values - `worktree | local | global | system`).
245
246- `.getConfig(key)` get the value(s) for a named key as a [ConfigGetResult](typings/response.d.ts)
247- `.getConfig(key, scope)` get the value(s) for a named key as a [ConfigGetResult](typings/response.d.ts) but limit the
248 scope of the properties searched to a single specified scope (use the exported `GitConfigScope` enum, or equivalent
249 string values - `worktree | local | global | system`)
250
251- `.listConfig()` reads the current configuration and returns a [ConfigListSummary](./src/lib/responses/ConfigList.ts)
252- `.listConfig(scope: GitConfigScope)` as with `listConfig` but returns only those items in a specified scope (note that configuration values are overlaid on top of each other to build the config `git` will actually use - to resolve the configuration you are using use `(await listConfig()).all` without the scope argument)
253
254## git hash-object
255
256- `.hashObject(filePath, write = false)` computes the object ID value for the contents of the named file (which can be
257 outside of the work tree), optionally writing the resulting value to the object database.
258
259## git init
260
261- `.init(bare [, options])` initialize a repository using the boolean `bare` parameter to intialise a bare repository.
262 Any number of other arguments supported by [git init](https://git-scm.com/docs/git-init) can be supplied as an
263 [options](#how-to-specify-options) object/array.
264
265- `.init([options])` initialize a repository using any arguments supported by
266 [git init](https://git-scm.com/docs/git-init) supplied as an [options](#how-to-specify-options) object/array.
267
268## git log
269
270- `.log([options])` list commits between `options.from` and `options.to` tags or branch (if not specified will
271 show all history). Use the `options` object to set any [options](#how-to-specify-options) supported by the
272 [git log](https://git-scm.com/docs/git-log) command or any of the following:
273
274 - `options.file` - the path to a file in your repository to only consider this path.
275 - `options.format` - custom log format object, keys are the property names used on the returned object, values are the format string from [pretty formats](https://git-scm.com/docs/pretty-formats#Documentation/pretty-formats.txt)
276 - `options.from` - when supplied along with `options.to` sets the range of commits to log
277 - `options.mailMap` - defaults to true, enables the use of [mail map](https://git-scm.com/docs/gitmailmap) in returned values for email and name from the default format
278 - `options.maxCount` - equivalent to setting the `--max-count` option
279 - `options.multiLine` - enables multiline body values in the default format (disabled by default)
280 - `options.splitter` - the character sequence to use as a delimiter between fields in the log, should be a value that doesn't appear in any log message (defaults to ` ò `)
281 - `options.strictDate` - switches the authored date value from an ISO 8601-like format to be strict ISO 8601 format
282 - `options.symmetric` - defaults to true, enables [symmetric revision range](https://git-scm.com/docs/gitrevisions#_dotted_range_notations) rather than a two-dot range
283 - `options.to` - when supplied along with `options.from` sets the range of commits to log
284
285## git merge
286
287- `.merge(options)` runs a merge using any configuration [options](#how-to-specify-options) supported
288 by [git merge](https://git-scm.com/docs/git-merge).
289 Conflicts during the merge result in an error response, the response is an instance of
290 [MergeSummary](src/lib/responses/MergeSummary.ts) whether it was an error or success.
291 When successful, the MergeSummary has all detail from a the [PullSummary](src/lib/responses/PullSummary.ts)
292 along with summary detail for the merge.
293 When the merge failed, the MergeSummary contains summary detail for why the merge failed and which files
294 prevented the merge.
295
296- `.mergeFromTo(remote, branch [, options])` - merge from the specified branch into the currently checked out branch,
297 similar to `.merge` but with the `remote` and `branch` supplied as strings separately to any additional
298 [options](#how-to-specify-options).
299
300## git mv
301
302- `.mv(from, to)` rename or move a single file at `from` to `to`
303
304- `.mv(from, to)` move all files in the `from` array to the `to` directory
305
306## git pull
307
308- `.pull([options])` pulls all updates from the default tracked remote, any arguments supported by
309 [git pull](https://git-scm.com/docs/git-pull) can be supplied as an [options](#how-to-specify-options) object/array.
310
311- `.pull(remote, branch[, options])` pulls all updates from the specified remote branch (eg 'origin'/'master') along
312 with any custom [options](#how-to-specify-options) object/array
313
314## git push
315
316- `.push([options])` pushes to a named remote/branch using any supported [options](#how-to-specify-options)
317 from the [git push](https://git-scm.com/docs/git-push) command. Note that `simple-git` enforces the use of
318 `--verbose --porcelain` options in order to parse the response. You don't need to supply these options.
319
320- `.push(remote, branch[, options])` pushes to a named remote/branch, supports additional
321 [options](#how-to-specify-options) from the [git push](https://git-scm.com/docs/git-push) command.
322
323- `.pushTags(remote[, options])` pushes local tags to a named remote (equivalent to using `.push([remote, '--tags'])`)
324
325## git remote
326
327- `.addRemote(name, repo, [options])` adds a new named remote to be tracked as `name` at the path `repo`, optionally with any supported [options](#how-to-specify-options) for the [git add](https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emaddem) call.
328- `.getRemotes([verbose])` gets a list of the named remotes, supply the optional `verbose` option as `true` to include the URLs and purpose of each ref
329- `.listRemote([options])` lists remote repositories - there are so many optional arguments in the underlying `git ls-remote` call, just supply any you want to use as the optional [options](#how-to-specify-options) eg: `git.listRemote(['--heads', '--tags'], console.log)`
330- `.remote([options])` runs a `git remote` command with any number of [options](#how-to-specify-options)
331- `.removeRemote(name)` removes the named remote
332
333## git reset
334
335- `.reset(resetMode, [resetOptions])` resets the repository, sets the reset mode to one of the supported types (use a constant from
336 the exported `ResetMode` enum, or a string equivalent: `mixed`, `soft`, `hard`, `merge`, `keep`). Any number of other arguments
337 supported by [git reset](https://git-scm.com/docs/git-reset) can be supplied as an [options](#how-to-specify-options) object/array.
338
339- `.reset(resetOptions)` resets the repository with the supplied [options](#how-to-specify-options)
340
341- `.reset()` resets the repository in `soft` mode.
342
343## git rev-parse / repo properties
344
345- `.revparse([options])` sends the supplied [options](#how-to-specify-options) to [git rev-parse](https://git-scm.com/docs/git-rev-parse) and returns the string response from `git`.
346
347- `.checkIsRepo()` gets whether the current working directory is a descendent of a git repository.
348- `.checkIsRepo('bare')` gets whether the current working directory is within a bare git repo (see either [git clone --bare](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---bare) or [git init --bare](https://git-scm.com/docs/git-init#Documentation/git-init.txt---bare)).
349- `.checkIsRepo('root')` gets whether the current working directory is the root directory for a repo (sub-directories will return false).
350
351## git status
352
353- `.status([options])` gets the status of the current repo, resulting in a [StatusResult](typings/response.d.ts). Additional arguments
354 supported by [git status](https://git-scm.com/docs/git-status) can be supplied as an [options](#how-to-specify-options) object/array.
355
356## git submodule
357
358- `.subModule(options)` Run a `git submodule` command with on or more arguments passed in as an [options](#how-to-specify-options) array or object
359- `.submoduleAdd(repo, path)` Adds a new sub module
360- `.submoduleInit([options]` Initialises sub modules, the optional [options](#how-to-specify-options) argument can be used to pass extra options to the `git submodule init` command.
361- `.submoduleUpdate(subModuleName, [options])` Updates sub modules, can be called with a sub module name and [options](#how-to-specify-options), just the options or with no arguments
362
363## changing the working directory [examples](examples/git-change-working-directory.md)
364
365- `.cwd(workingDirectory)` Sets the working directory for all future commands - note, this will change the working for the root instance, any chain created from the root will also be changed.
366- `.cwd({ path, root = false })` Sets the working directory for all future commands either in the current chain of commands (where `root` is omitted or set to `false`) or in the main instance (where `root` is `true`).
367
368# How to Specify Options
369
370Where the task accepts custom options (eg: `pull` or `commit`), these can be supplied as an object, the keys of which
371will all be merged as trailing arguments in the command string, or as a simple array of strings.
372
373## Options as an Object
374
375When the value of the property in the options object is a `string`, that name value
376pair will be included in the command string as `name=value`. For example:
377
378```javascript
379// results in 'git pull origin master --no-rebase'
380git().pull('origin', 'master', {'--no-rebase': null})
381
382// results in 'git pull origin master --rebase=true'
383git().pull('origin', 'master', {'--rebase': 'true'})
384```
385
386## Options as an Array
387
388Options can also be supplied as an array of strings to be merged into the task's commands
389in the same way as when an object is used:
390
391```javascript
392//
393git.pull('origin', 'master', ['--no-rebase'])
394```
395
396# Release History
397
398Major release 2.x changes the way the queue of tasks are handled to use promises internally and makes
399available the `.then` and `.catch` methods for integrating with promise consumers or async await.
400
401TypeScript is used by default for all new code, allowing for auto-generated type definitions and a phased
402re-write of the library rather than a big-bang.
403
404For a per-release overview of changes, see the [changelog](./CHANGELOG.md).
405
406## 2.x Upgrade Notes
407
408When upgrading to release 2.x from 1.x, see the [changelog](./CHANGELOG.md) for the release 2.0.0
409
410# Recently Deprecated / Altered APIs
411
412- ~~2.25.0 depends on Node.js version 12 or above, for use in lower versions of node.js ensure you are also
413 importing the necessary polyfills from `core-js`, see [Legacy Node Versions](./docs/LEGACY_NODE_VERSIONS.md)~~
414 _this change has been reverted in 2.30.0 and will be postponed until version 3.x_.
415
416- 2.13.0 `.push` now returns a [PushResult](./typings/response.d.ts) parsed representation of the response.
417
418- 2.11.0 treats tasks chained together as atomic, where any failure in the chain prevents later tasks from
419 executing and tasks called from the root `git` instance as the origin of a new chain, and able to be
420 [run in parallel](#concurrent--parallel-requests) without failures impacting one anther. Prior to this
421 version, tasks called on the root `git` instance would be cancelled when another one failed.
422
423- 2.7.0 deprecates use of `.silent()` in favour of using the `debug` library - see the
424 [debug logging guide](docs/DEBUG-LOGGING-GUIDE.md) for further details.
425
426- 2.6.0 introduced `.then` and `.catch` as a way to chain a promise onto the current step of the chain.
427Importing from `simple-git/promise` instead of just `simple-git` is no longer required and is actively discouraged.
428
429For the full history see the [changelog](./CHANGELOG.md);
430
431# Concurrent / Parallel Requests
432
433When the methods of `simple-git` are chained together, they create an execution chain that will run in series,
434useful for when the tasks themselves are order-dependent, eg:
435
436```typescript
437const git = simpleGit();
438git.init().addRemote('origin', 'https://some-repo.git').fetch();
439```
440
441Each task requires that the one before it has been run successfully before it is called, any errors in a
442step of the chain should prevent later steps from being attempted.
443
444When the methods of `simple-git` are called on the root instance (ie: `git = simpleGit()`) rather than chained
445off another task, it starts a new chain and will not be affected failures in tasks already being run. Useful
446for when the tasks are independent of each other, eg:
447
448```typescript
449const git = simpleGit();
450const results = await Promise.all([
451 git.raw('rev-parse', '--show-cdup').catch(swallow),
452 git.raw('rev-parse', '--show-prefix').catch(swallow),
453]);
454function swallow (err) { return null }
455```
456
457Each `simple-git` instance limits the number of spawned child processes that can be run simultaneously and
458manages the queue of pending tasks for you. Configure this value by passing an options object to the
459`simpleGit` function, eg:
460
461```typescript
462const git = simpleGit({ maxConcurrentProcesses: 10 });
463```
464
465Treating tasks called on the root instance as the start of separate chains is a change to the behaviour of
466 `simple-git` and was added in version `2.11.0`.
467
468# Complex Requests
469
470When no suitable wrapper exists in the interface for creating a request, it is possible to run a command directly
471using `git.raw([...], handler)`. The array of commands are passed directly to the `git` binary:
472
473```js
474const git = require('simple-git');
475const path = '/path/to/repo';
476const commands = [ 'config', '--global', 'advice.pushNonFastForward', 'false' ];
477
478// using an array of commands
479git(path).raw(commands, (err, result) => {
480
481 // err is null unless this command failed
482 // result is the raw output of this command
483
484});
485
486// using a var-args of strings and awaiting rather than using the callback
487const result = await git(path).raw(...commands);
488```
489
490# Authentication
491
492The easiest way to supply a username / password to the remote host is to include it in the URL, for example:
493
494```js
495const USER = 'something';
496const PASS = 'somewhere';
497const REPO = 'github.com/username/private-repo';
498
499const git = require('simple-git');
500const remote = `https://${USER}:${PASS}@${REPO}`;
501
502git().silent(true)
503 .clone(remote)
504 .then(() => console.log('finished'))
505 .catch((err) => console.error('failed: ', err));
506
507```
508
509Be sure to enable silent mode to prevent fatal errors from being logged to stdout.
510
511# Environment Variables
512
513Pass one or more environment variables to the child processes spawned by `simple-git` with the `.env` method which
514supports passing either an object of name=value pairs or setting a single variable at a time:
515
516```js
517const GIT_SSH_COMMAND = "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no";
518
519const git = require('simple-git');
520
521git()
522 .env('GIT_SSH_COMMAND', GIT_SSH_COMMAND)
523 .status((err, status) => { /* */ })
524
525git().env({ ...process.env, GIT_SSH_COMMAND })
526 .status()
527 .then(status => { })
528 .catch(err => {});
529
530```
531
532Note - when passing environment variables into the child process, these will replace the standard `process.env`
533variables, the example above creates a new object based on `process.env` but with the `GIT_SSH_COMMAND` property
534added.
535
536# TypeScript
537
538To import with TypeScript:
539
540```typescript
541import simpleGit, { SimpleGit, StatusResult } from 'simple-git';
542
543const git: SimpleGit = simpleGit();
544const status: StatusResult = await git.status();
545```
546
547# Promise and async compatible
548
549For each task run, the return is the same `SimpleGit` instance for ease of building
550a series of tasks that all run sequentially and are treated as atomic (ie: if any
551step fails, the later tasks are not attempted).
552
553To work with promises (either directly or as part of async/await), simply call the
554function as before:
555
556```js
557const simpleGit = require('simple-git');
558const git = simpleGit();
559
560// async / await
561const status = await git.status();
562
563// promise
564git.status().then(result => {...});
565```
566
567# Exception Handling
568
569When the `git` process exits with a non-zero status (or in some cases like `merge` the git
570process exits with a successful zero code but there are conflicts in the merge) the task
571will reject with a `GitError` when there is no available parser to handle the error or a
572`GitResponseError` for when there is.
573
574See the `err` property of the callback:
575
576```javascript
577git.merge((err, mergeSummary) => {
578 if (err.git) {
579 mergeSummary = err.git; // the failed mergeSummary
580 }
581})
582```
583
584Catch errors with try/catch in async code:
585
586```javascript
587try {
588 const mergeSummary = await git.merge();
589 console.log(`Merged ${ mergeSummary.merges.length } files`);
590}
591catch (err) {
592 // err.message - the string summary of the error
593 // err.stack - some stack trace detail
594 // err.git - where a parser was able to run, this is the parsed content
595
596 console.error(`Merge resulted in ${ err.git.conflicts.length } conflicts`);
597}
598```
599
600Catch errors with a `.catch` on the promise:
601
602```javascript
603const mergeSummary = await git.merge()
604 .catch(err => {
605 if (err.git) { return err.git; } // the unsuccessful mergeSummary
606 throw err; // some other error, so throw
607 });
608
609if (mergeSummary.failed) {
610 console.error(`Merge resulted in ${ mergeSummary.conflicts.length } conflicts`);
611}
612```
613
614With typed errors available in TypeScript
615
616```typescript
617import simpleGit, { MergeSummary, GitResponseError } from 'simple-git';
618try {
619 const mergeSummary = await simpleGit().merge();
620 console.log(`Merged ${ mergeSummary.merges.length } files`);
621}
622catch (err) {
623 // err.message - the string summary of the error
624 // err.stack - some stack trace detail
625 // err.git - where a parser was able to run, this is the parsed content
626 const mergeSummary: MergeSummary = (err as GitResponseError<MergeSummary>).git;
627 const conflicts = mergeSummary?.conflicts || [];
628
629 console.error(`Merge resulted in ${ conflicts.length } conflicts`);
630}
631```
632
633# Troubleshooting / FAQ
634
635### Enable logging
636
637See the [debug logging guide](docs/DEBUG-LOGGING-GUIDE.md) for logging examples and how to
638make use of the [debug](https://www.npmjs.com/package/debug) library's programmatic interface
639in your application.
640
641### Enable Verbose Logging
642
643See the [debug logging guide](docs/DEBUG-LOGGING-GUIDE.md#verbose-logging-options) for
644the full list of verbose logging options to use with the
645[debug](https://www.npmjs.com/package/debug) library.
646
647### Every command returns ENOENT error message
648
649There are a few potential reasons:
650
651- `git` isn't available as a binary for the user running the main `node` process, custom paths to the binary can be used
652 with the `.customBinary(...)` api option.
653
654- the working directory passed in to the main `simple-git` function isn't accessible, check it is read/write accessible
655 by the user running the `node` process. This library uses
656 [@kwsites/file-exists](https://www.npmjs.com/package/@kwsites/file-exists) to validate the working directory exists,
657 to output its logs add `@kwsites/file-exists` to your `DEBUG` environment variable. eg:
658
659 `DEBUG=@kwsites/file-exists,simple-git node ./your-app.js`
660
661### Log format fails
662
663The properties of `git log` are fetched using the `--pretty=format` argument which supports different tokens depending
664on the version of `git` - for example the `%D` token used to show the refs was added in git `2.2.3`, for any version
665before that please ensure you are supplying your own format object with properties supported by the version of git you
666are using.
667
668For more details of the supported tokens, please see the
669[official `git log` documentation](https://git-scm.com/docs/git-log#_pretty_formats)
670
671### Log response properties are out of order
672
673The properties of `git.log` are fetched using the character sequence ` ò ` as a delimiter. If your commit messages
674use this sequence, supply a custom `splitter` in the options, for example: `git.log({ splitter: '💻' })`
675
676### Pull / Diff / Merge summary responses don't recognise any files
677
678- Enable verbose logs with the environment variable `DEBUG=simple-git:task:*,simple-git:output:*`
679- Check the output (for example: `simple-git:output:diff:1 [stdOut] 1 file changed, 1 insertion(+)`)
680- Check the `stdOut` output is the same as you would expect to see when running the command directly in terminal
681- Check the language used in the response is english locale
682
683In some cases `git` will show progress messages or additional detail on error states in the output for
684`stdErr` that will help debug your issue, these messages are also included in the verbose log.
685
686### Legacy Node Versions
687
688From `v3.x`, `simple-git` will drop support for `node.js` version 10 or below, to use in a lower version of
689node will result in errors such as:
690
691- `Object.fromEntries is not a function`
692- `Object.entries is not a function`
693- `message.flatMap is not a function`
694
695To resolve these issues, either upgrade to a newer version of node.js or ensure you are using the necessary
696polyfills from `core-js` - see [Legacy Node Versions](./docs/LEGACY_NODE_VERSIONS.md).
697
698# Examples
699
700
701### using a pathspec to limit the scope of the task
702
703If the `simple-git` api doesn't explicitly limit the scope of the task being run (ie: `git.add()` requires the files to
704be added, but `git.status()` will run against the entire repo), add a `pathspec` to the command using trailing options:
705
706```typescript
707const git = simpleGit();
708const wholeRepoStatus = await git.status();
709const subDirStatusUsingOptArray = await git.status(['--', 'sub-dir']);
710const subDirStatusUsingOptObject = await git.status({'--': null, 'sub-dir': null});
711```
712
713### async await
714
715```javascript
716async function status (workingDir) {
717 const git = require('simple-git');
718
719 let statusSummary = null;
720 try {
721 statusSummary = await git(workingDir).status();
722 }
723 catch (e) {
724 // handle the error
725 }
726
727 return statusSummary;
728}
729
730// using the async function
731status(__dirname + '/some-repo').then(status => console.log(status));
732```
733
734### Initialise a git repo if necessary
735
736```javascript
737const simpleGit = require('simple-git');
738const git = simpleGit(__dirname);
739
740git.checkIsRepo()
741 .then(isRepo => !isRepo && initialiseRepo(git))
742 .then(() => git.fetch());
743
744function initialiseRepo (git) {
745 return git.init()
746 .then(() => git.addRemote('origin', 'https://some.git.repo'))
747}
748```
749
750### Update repo and get a list of tags
751
752```javascript
753require('simple-git')(__dirname + '/some-repo')
754 .pull()
755 .tags((err, tags) => console.log("Latest available tag: %s", tags.latest));
756
757// update repo and when there are changes, restart the app
758require('simple-git')()
759 .pull((err, update) => {
760 if(update && update.summary.changes) {
761 require('child_process').exec('npm restart');
762 }
763 });
764```
765
766### Starting a new repo
767
768```javascript
769require('simple-git')()
770 .init()
771 .add('./*')
772 .commit("first commit!")
773 .addRemote('origin', 'https://github.com/user/repo.git')
774 .push('origin', 'master');
775```
776
777### push with `-u`
778
779```js
780require('simple-git')()
781 .add('./*')
782 .commit("first commit!")
783 .addRemote('origin', 'some-repo-url')
784 .push(['-u', 'origin', 'master'], () => console.log('done'));
785```
786
787### Piping to the console for long-running tasks
788
789```js
790require('simple-git')()
791 .outputHandler((bin, stdout, stderr, args) => {
792 stdout.pipe(process.stdout);
793 stderr.pipe(process.stderr);
794
795 // the name of the binary used, defaults to git, see customBinary for more info
796 assert.equal(bin, 'git');
797
798 // all other arguments passsed to the binary
799 assert.deepEqual(args, ['checkout', 'https://github.com/user/repo.git']);
800 })
801 .checkout('https://github.com/user/repo.git');
802```
803
804### Update repo and print messages when there are changes, restart the app
805
806```javascript
807// when using a chain
808require('simple-git')()
809 .exec(() => console.log('Starting pull...'))
810 .pull((err, update) => {
811 if(update && update.summary.changes) {
812 require('child_process').exec('npm restart');
813 }
814 })
815 .exec(() => console.log('pull done.'));
816
817// when using async and optional chaining
818const git = require('simple-git')()
819console.log('Starting pull...')
820if ((await git.pull())?.summary.changes) {
821 require('child_process').exec('npm restart');
822}
823console.log('pull done.');
824
825```
826
827### Get a full commits list, and then only between 0.11.0 and 0.12.0 tags
828
829```javascript
830require('simple-git')()
831 .log((err, log) => console.log(log))
832 .log('0.11.0', '0.12.0', (err, log) => console.log(log));
833```
834
835### Set the local configuration for author, then author for an individual commit
836
837```javascript
838require('simple-git')()
839 .addConfig('user.name', 'Some One')
840 .addConfig('user.email', 'some@one.com')
841 .commit('committed as "Some One"', 'file-one')
842 .commit('committed as "Another Person"', 'file-two', { '--author': '"Another Person <another@person.com>"' });
843```
844
845### Get remote repositories
846
847```javascript
848require('simple-git')()
849 .listRemote(['--get-url'], (err, data) => {
850 if (!err) {
851 console.log('Remote url for repository at ' + __dirname + ':');
852 console.log(data);
853 }
854 });
855```