Repository: okonet/lint-staged
Pull request #888 (2020-06-12 17:12:17)

fix: run all git commands with submodule.recurse=false
This explicitly prevents git commands from recursing into git submodules and thus causing issues with commands like stash or reset.

Fixes https://github.com/okonet/lint-staged/issues/884

codecov[bot]: # [Codecov](https://codecov.io/gh/okonet/lint-staged/pull/888?src=pr&el=h1) Report
> Merging [#888](https://codecov.io/gh/okonet/lint-staged/pull/888?src=pr&el=desc) into [master](https://codecov.io/gh/okonet/lint-staged/commit/a1904ec6a96b04cd93eeb622b04cf328a10083df&el=desc) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/okonet/lint-staged/pull/888/graphs/tree.svg?width=650&height=150&src=pr&token=LSoEgsjk4O)](https://codecov.io/gh/okonet/lint-staged/pull/888?src=pr&el=tree)

```diff
@@            Coverage Diff            @@
##            master      #888   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           17        17           
  Lines          599       602    +3     
  Branches       142       142           
=========================================
+ Hits           599       602    +3     
```


| [Impacted Files](https://codecov.io/gh/okonet/lint-staged/pull/888?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [lib/execGit.js](https://codecov.io/gh/okonet/lint-staged/pull/888/diff?src=pr&el=tree#diff-bGliL2V4ZWNHaXQuanM=) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/okonet/lint-staged/pull/888?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/okonet/lint-staged/pull/888?src=pr&el=footer). Last update [a1904ec...a695237](https://codecov.io/gh/okonet/lint-staged/pull/888?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

iiroj: What do you think, @okonet?

Patch:
diff --git a/lib/execGit.js b/lib/execGit.js
index 8597e6c..7fb8ef1 100644
--- a/lib/execGit.js
+++ b/lib/execGit.js
@@ -3,10 +3,18 @@
 const debug = require('debug')('lint-staged:git')
 const execa = require('execa')
 
+/**
+ * Explicitly never recurse commands into submodules, overriding local/global configuration.
+ * @see https://git-scm.com/docs/git-config#Documentation/git-config.txt-submodulerecurse
+ */
+const NO_SUBMODULE_RECURSE = ['-c', 'submodule.recurse=false']
+
+const GIT_GLOBAL_OPTIONS = [...NO_SUBMODULE_RECURSE]
+
 module.exports = async function execGit(cmd, options = {}) {
   debug('Running git command', cmd)
   try {
-    const { stdout } = await execa('git', [].concat(cmd), {
+    const { stdout } = await execa('git', GIT_GLOBAL_OPTIONS.concat(cmd), {
       ...options,
       all: true,
       cwd: options.cwd || process.cwd(),
@@ -16,3 +24,6 @@ module.exports = async function execGit(cmd, options = {}) {
     throw new Error(all)
   }
 }
+
+// exported for tests
+module.exports.GIT_GLOBAL_OPTIONS = GIT_GLOBAL_OPTIONS


Test patch:
diff --git a/test/execGit.spec.js b/test/execGit.spec.js
index ac84f60..7990ab9 100644
--- a/test/execGit.spec.js
+++ b/test/execGit.spec.js
@@ -1,17 +1,33 @@
 import path from 'path'
 import execa from 'execa'
-import execGit from '../lib/execGit'
+
+import execGit, { GIT_GLOBAL_OPTIONS } from '../lib/execGit'
+
+test('GIT_GLOBAL_OPTIONS', () => {
+  expect(GIT_GLOBAL_OPTIONS).toMatchInlineSnapshot(`
+    Array [
+      "-c",
+      "submodule.recurse=false",
+    ]
+  `)
+})
 
 describe('execGit', () => {
   it('should execute git in process.cwd if working copy is not specified', async () => {
     const cwd = process.cwd()
     await execGit(['init', 'param'])
-    expect(execa).toHaveBeenCalledWith('git', ['init', 'param'], { all: true, cwd })
+    expect(execa).toHaveBeenCalledWith('git', [...GIT_GLOBAL_OPTIONS, 'init', 'param'], {
+      all: true,
+      cwd,
+    })
   })
 
   it('should execute git in a given working copy', async () => {
     const cwd = path.join(process.cwd(), 'test', '__fixtures__')
     await execGit(['init', 'param'], { cwd })
-    expect(execa).toHaveBeenCalledWith('git', ['init', 'param'], { all: true, cwd })
+    expect(execa).toHaveBeenCalledWith('git', [...GIT_GLOBAL_OPTIONS, 'init', 'param'], {
+      all: true,
+      cwd,
+    })
   })
 })