How to configure husky when .git is in a different folder?
Asked Answered
F

5

19

I'm trying to set up automatic linting on commit for my company's project, and the best way I've seen to do so has been the husky NPM package. I'm following instructions on setting up Husky with eslint , prettier , and lint-staged but I keep hitting on the same issue that I can't figure out how to resolve.

My problem is that my project is set up like so:

- Parent Directory
  - .git
  - Working Project Directory
    - node_modules
    - package.json

When i attempt to install husky, I get an error that I am missing the .git file, however it's there, just one level up in the file structure!!

I have seen some things in other posts about using the following technique to fix it:

npx mrm lint-staged This will fail, that’s expected

Then fix the npm prepare script "prepare": "husky install" -> "prepare": "cd .. && husky install some-folder/.husky"

Then run npm i

However it doesn't work for me.

I have also attempted to install husky in the parent directory but it doesn't quite work and it makes the install process of our project more difficult

Does anyone have any suggestions?

EDIT: Here is the error message I get:

% npx husky-ini
t && npm install
Need to install the following packages:
  husky-init
Ok to proceed? (y) y
husky-init updating package.json
  setting prepare script to command "husky install"
/Users/me/.npm/_npx/1ab9c0f68ac2536e/node_modules/husky/lib/index.js:22
        throw new Error(`.git can't be found (see ${url})`);
        ^

Error: .git can't be found (see https://typicode.github.io/husky/#/?id=custom-directory)
    at install (/Users/me/.npm/_npx/1ab9c0f68ac2536e/node_modules/husky/lib/index.js:22:15)
    at Object.<anonymous> (/Users/me/.npm/_npx/1ab9c0f68ac2536e/node_modules/husky-init/lib/bin.js:16:21)
Footage answered 19/10, 2022 at 17:8 Comment(4)
Where do you want to change those script? It should not be in your directory until it is installed.Borchardt
Maybe it will be better to somehow skip prepare script in your case and do it on your own. github.com/npm/rfcs/discussions/261Borchardt
When I try to install husky, it creates a prepare script automatically if I don't have one @BorchardtFootage
@Borchardt I edited my post to show the error that i'm gettingFootage
H
24

By default, husky assumes that your project's package.json file is at the same level as the .git file. In your case, as you say, they are at different levels.

To fix this, you should modify the package.json file.

Even though you have this error

   Error(`.git can't be found (see ${url})`);) 

you should have this inside the script

"scripts": {
 ...
 "prepare": "husky install"
 ...
}

You should replaceit by:

"scripts": {
   ...
   "prepare": "cd .. && husky install [child-folder]/.husky"
   ...
}

EXAMPLE:

  • parent-folder
    • .git
    • project-folder
      • node_modules
      • package.json

SOLUTION

"scripts": {
   ...
   "prepare": "cd .. && husky install project-folder/.husky"
   ...
}
Horse answered 4/1, 2023 at 20:41 Comment(2)
From the documentation you can see itOpposable
"husky install" is now deprecated, and didn't work for me. Use "husky [folder]" without "install".Copra
S
9

By default, husky supports monorepos, which means, all your code should be in 1 parent folder. But, if you have 2 different folders, as an example if you are building a fullstack app with frontend and backend folders, you need custom directory.

  1. First, install this:
npm i husky -D
  1. Go to the child folder package.json file and add this line
{
  "scripts": {
    "prepare": "cd .. && husky install [childFolderName]/.husky"
  }
}
  1. Run npm install
  2. You should be able to see a .husky folder after doing step 3 inside the child folder.
  3. create a file named pre-commit with no extensions, inside the .husky folder and add these basic lines and other stuffs
# ...
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
cd ./[childFolderName] && npm test

Done ! Hope it helps. For more reference, putting the official docs here : https://typicode.github.io/husky/guide.html

Slyviasm answered 13/7, 2023 at 4:16 Comment(1)
"husky install" is now deprecated, and didn't work for me. Use "husky [folder]" without "install".Copra
G
4

Got same issue solved with this way:

Step-1: you have Locate the .git directory

Example file structure like this (git is inside the parent folder[ADMIN]),

 .ADMIN
 ├── .git/
 ├── folder_1/  [ No package.json ]
 └── folder_2/  [ Contains Package.json with .husky]

Step-2: Add a prepare script in the Package.json of folder_2

 "scripts": {
    "prepare": "cd .. && husky folder_1/.husky" //put this line and put your directory name
  },

Step-3: Run npm run prepare to generate the .husky directory and its contents. then you will see directory .husky inside the folder_2 like this

enter image description here

Step-4: then all you have to do , create new file inside .husky/pre-commit

enter image description here

Step-5: Inside .husky/pre-commit, add the following:

. "$(dirname -- "$0")/_/husky.sh"

cd folder_2
npm run compile
npx pretty-quick --staged
npm run lint

Make sure to replace the example commands (npm run compile, npx pretty-quick --staged, npm run lint) with your actual commands for compilation, formatting, and linting.

Garb answered 20/2, 2024 at 16:13 Comment(1)
Thank you very much for your answer. You saved my time :)Title
U
0

I got stuck in the same issue && here is the solution I came up with:

*** If you don't have a package.json in Parent Directory, you should create one with npm init -y ***

  • in Parent Directory: npm install husky --save-dev
  • in Parent Directory: npx husky install Working Project Directory/.husky
  • in Parent Directory: npx husky add Working Project Directory/.husky/pre-commit "cd Working Project Directory && npm run test"

This worked for me

Unthankful answered 16/5, 2023 at 13:9 Comment(0)
S
0

Mine .git directory had parent level nesting . So I had to go upto 7 levels in prepare script like "prepare" : cd ../../../../ && husky install. This doesnt look good as code readability. So i ended up creating script where it finds .git directory and configures husky where the .git directory is found.

import { execSync } from 'child_process';
import { existsSync } from 'fs';
import { join,resolve } from 'path';

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function findGitRoot(directory: string) {
    const gitPath = join(directory,'.git');
    if(existsSync(gitPath)) {
        return directory;
    }
    const parentDirectory = resolve (directory, '..');
    if(parentDirectory === directory) {
        return null; // Reached File System root
    }
    return findGitRoot(parentDirectory);
}

try {
    const projectRoot = process.cwd();
    console.log('Currenty working directory',projectRoot);
    const gitRoot = findGitRoot(projectRoot); //Find .git directory
    if(gitRoot) {
        //Execute husky install
        console.log('Gitpath found',gitRoot);
        process.chdir(gitRoot);
        execSync('npx husky', {stdio: 'inherit'});
        console.log('Husky installed Successfully');
    } else {
        console.error('No .git directory found');
    }
} catch(error) {
    console.error('Failed to install husky config',error);
}
Stedfast answered 3/3, 2024 at 10:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.