Search code examples
pythongitgitpython

Is it possible to emulate `git add -A` in GitPython?


I've recently discovered GitPython, and, given that I'm currently trying to create a Python script which pushes to and pulls from Git repositories automatically, I was really excited to try it out.

When committing to a repository using command line Git, I call git add -A, pretty much to the exclusion of all other arguments. I know that you can call git add . instead, or add/remove files by name; I've just never felt the need to use that functionality. (Is that bad practice on my part?) However, I've been trying to put together a GitPython script today, and, despite combing through the API reference, I can't find any straightforward way of emulating the git add -A command.

This is a snippet from my efforts so far:

repo = Repo(absolute_path)
repo.index.add("-A")
repo.index.commit("Commit message.")
repo.remotes.origin.push()

This throws the following error: FileNotFoundError: [Errno 2] No such file or directory: '-A'. If, instead, I try to call repo.index.add(), I get: TypeError: add() missing 1 required positional argument: 'items'. I understand that .add() wants me to specify the files I want to add by name, but the whole point of GitPython, from my point of view, is that it's automated! Having to name the files manually defeats the purpose of the module!

Is it possible to emulate git add -A in GitPython? If so, how?


Solution

  • The API you linked goes to a version of GitPython that supports invoking the Git binaries themselves directly, so you could just have it run git add -A for you.

    That aside, git add -A means:

    Update the index not only where the working tree has a file matching <pathspec> but also where the index already has an entry. This adds, modifies, and removes index entries to match the working tree.

    If no <pathspec> is given when -A option is used, all files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories).

    So git add -A is just the same as git add . from the top level of the working tree. If you want the old (pre-2.0) git add -A behavior, run git add . from a lower level of the working tree; to get the 2.0-or-later git add -A behavior, run git add . from the top level of the working tree. But see also --no-all:

    This option is primarily to help users who are used to older versions of Git, whose "git add <pathspec>…​" was a synonym for "git add --no-all <pathspec>…​", i.e. ignored removed files.

    So, if you want the pre-2.0 behavior, you will also need --no-all.

    If you intend to do all of these within GitPython without using the git.cmd.Git class, I'll also add that in my experience, the various Python implementations of bits of Git vary in their fidelity to fiddly matters like --no-all (and/or their mapping to pre-2.0 Git, post-2.0 Git, post-2.23 Git, etc.), so if you intend to depend on these behaviors, you should test them.