Isomorphic-git: How to add all untracked files with git.add?

Created on 15 May 2018  路  5Comments  路  Source: isomorphic-git/isomorphic-git

Hi,
I'm looking for a way init a git repo, add all existing files, and commit them, while if I understand correctly, the git.add function needs me to give all of the files explicitly.

Is there a way that I can add all of the files in one or two command?

faq

Most helpful comment

TLDR

const globby = require('globby');
const paths = await globby(['./**', './**/.*'], { gitignore: true });
for (const filepath of paths) {
    await git.add({ fs, dir, filepath });
}

Long answer
Good question! I didn't add an "add all" function because you almost always want to make an exception or two, and the general category of "get me a list of all the files matching some pattern" is pretty well covered by existing modules on npm. But a good example to demonstrate it would be something I should add that to the FAQ. (\

How's about this recipe? Here I use globby because it has a super nifty feature: it can understand .gitignore files! (It's written for node... I haven't tested whether globby is compatible with BrowserFS.)

#!/usr/bin/env node
const globby = require('globby');
const git = require('isomorphic-git');
const fs = require('fs');
const dir = process.cwd();

(async () => {
    await git.init({ fs, dir });
    const paths = await globby(['./**', './**/.*', '!node_modules'], { gitignore: true });
    for (const filepath of paths) {
        await git.add({ fs, dir, filepath });
    }
    await git.config({ fs, dir, path: 'user.name', value: 'Some User' });
    await git.config({ fs, dir, path: 'user.email', value: '[email protected]' });
    await git.commit({ fs, dir, message: 'Initial commit' })
})();

I'll break this example down to make things clearer:

(async () => {

Until await is allowed at the module level, we have to wrap await statements in an immediately invoked anonymous async function, or else use the .then() syntax for dealing with promises.

    const paths = await globby(['./**', './**/.*', '!node_modules'], { gitignore: true });

This tells globby to:

  • ./** = match all regular files
  • ./**/.* = match all "hidden" dot files, like .babelrc or .travis.yml
  • !node_modules = exclude the node_modules folder
  • { gitignore: true} = also respect the patterns in .gitignore files
    for (const filepath of paths) {
        await git.add({ fs, dir, filepath });
    }

This is a loop that calls git.add for each file.

    await git.config({ fs, dir, path: 'user.name', value: 'Some User' });
    await git.config({ fs, dir, path: 'user.email', value: '[email protected]' });
    await git.commit({ fs, dir, message: 'Initial commit' })

git.commit will throw an error if no author information is available. Here I'm saving it to the repo's local config file so that you won't have to enter that information each time you commit. But you can alternatively pass that information as an argument, e.g.

        await git.add({ fs, dir, filepath, author: {name: 'Some User', email: '[email protected]' }})

Whew! This turned into a longer answer than I expected. Hope it helps!!

All 5 comments

TLDR

const globby = require('globby');
const paths = await globby(['./**', './**/.*'], { gitignore: true });
for (const filepath of paths) {
    await git.add({ fs, dir, filepath });
}

Long answer
Good question! I didn't add an "add all" function because you almost always want to make an exception or two, and the general category of "get me a list of all the files matching some pattern" is pretty well covered by existing modules on npm. But a good example to demonstrate it would be something I should add that to the FAQ. (\

How's about this recipe? Here I use globby because it has a super nifty feature: it can understand .gitignore files! (It's written for node... I haven't tested whether globby is compatible with BrowserFS.)

#!/usr/bin/env node
const globby = require('globby');
const git = require('isomorphic-git');
const fs = require('fs');
const dir = process.cwd();

(async () => {
    await git.init({ fs, dir });
    const paths = await globby(['./**', './**/.*', '!node_modules'], { gitignore: true });
    for (const filepath of paths) {
        await git.add({ fs, dir, filepath });
    }
    await git.config({ fs, dir, path: 'user.name', value: 'Some User' });
    await git.config({ fs, dir, path: 'user.email', value: '[email protected]' });
    await git.commit({ fs, dir, message: 'Initial commit' })
})();

I'll break this example down to make things clearer:

(async () => {

Until await is allowed at the module level, we have to wrap await statements in an immediately invoked anonymous async function, or else use the .then() syntax for dealing with promises.

    const paths = await globby(['./**', './**/.*', '!node_modules'], { gitignore: true });

This tells globby to:

  • ./** = match all regular files
  • ./**/.* = match all "hidden" dot files, like .babelrc or .travis.yml
  • !node_modules = exclude the node_modules folder
  • { gitignore: true} = also respect the patterns in .gitignore files
    for (const filepath of paths) {
        await git.add({ fs, dir, filepath });
    }

This is a loop that calls git.add for each file.

    await git.config({ fs, dir, path: 'user.name', value: 'Some User' });
    await git.config({ fs, dir, path: 'user.email', value: '[email protected]' });
    await git.commit({ fs, dir, message: 'Initial commit' })

git.commit will throw an error if no author information is available. Here I'm saving it to the repo's local config file so that you won't have to enter that information each time you commit. But you can alternatively pass that information as an argument, e.g.

        await git.add({ fs, dir, filepath, author: {name: 'Some User', email: '[email protected]' }})

Whew! This turned into a longer answer than I expected. Hope it helps!!

I've look at globby index.js in jsdeliver cdn and it's node module (with node dependencies with require) it will not work in browser.

But with BrowserFS you can use this function based on this https://gist.github.com/slav123/8118962 it only use fs.

function listFiles(startDir, usePath, callback) {
    if (arguments.length === 2 && typeof arguments[1] === 'function') {
        callback = usePath;
        usePath = false;
    }
    //Hold onto the array of items
    var parsedDirectory = [];
    //start reading a list of whats contained
    fs.readdir(startDir, function(err, dirList) {
        if (usePath) {
            startDir = fs.realpathSync(startDir);
        }
        if (err) {
            return callback(err);
        }
        //keep track of how deep we need to go before callback
        var listlength = dirList.length;
        if (!listlength) {
            return callback(null, parsedDirectory);
        }
        //loop through the directory list
        dirList.forEach(function(file) {
            file = (startDir === '/' ? '' : startDir) + '/' + file;
            fs.stat(file, function(err, stat) {
                //note the directory or file
                if (stat && stat.isFile()) parsedDirectory.push(file);
                //recursive if this is a directory
                if (stat && stat.isDirectory()) {
                    //recurse
                    listFiles(file, function(err, parsed) {
                        // read this directory into our output
                        parsedDirectory = parsedDirectory.concat(parsed);
                        //check to see if we've exhausted our search
                        if (!--listlength) {
                            callback(null, parsedDirectory);
                        }
                    });
                } else {
                    //check to see if we've exhausted the search
                    if (!--listlength) {
                        callback(null, parsedDirectory);
                    }
                }
            });
        });
    });
}

It helped definitely! Thanks a lot!

@jcubic I bet with the right webpack config we could get globby to run in the browser. 馃榾

Finally added this to the FAQ (which finally exists): https://isomorphic-git.org/docs/en/faq#how-to-add-all-untracked-files-with-gitadd

Was this page helpful?
0 / 5 - 0 ratings

Related issues

creationix picture creationix  路  4Comments

willstott101 picture willstott101  路  4Comments

TomasHubelbauer picture TomasHubelbauer  路  6Comments

hsablonniere picture hsablonniere  路  4Comments

aanavaneeth picture aanavaneeth  路  3Comments