fboender / multi-git-status

Show uncommitted, untracked and unpushed changes for multiple Git repos
MIT License
470 stars 73 forks source link

targeting git repos with a nonstandard name/path? #26

Open abathur opened 5 years ago

abathur commented 5 years ago

It would be nice to be able to point mgitstatus at nonstandard git repos.

My personal use-case is the yadm dotfile manager https://github.com/TheLocehiliosan/yadm, which is uses a distinct path. Typically we'd just interact with that repo via yadm <git-sub-command>..., but we can also do something like GIT_DIR=~/.yadm/git.repo git status to run plain git commands against it.

I'm not sure what's best in terms of syntax/implementation (I can imagine a few different ways...) but a fairly simple idea is a flag to specify one -name to the find command. For example, I can use something like this to match all of the git repositories mgitstatus finds, plus the yadm repo I mentioned: find -L . -maxdepth 3 -type d -name "*.git" (I had to adjust the maxdepth up 1, though, since that's matching deeper in the tree).

abathur commented 5 years ago

Another (more flexible, but maybe overkill?) option would just be, whether through accepting paths last with a flag to change the meaning, or a git-style -- path separator, support passing an explicit list of paths directly to the git repositories themselves, and let the user do whatever makes sense in their case.

fboender commented 5 years ago

If I understand you correctly, you mean support for work trees that are different than the location of the .git dir? I think they're called "detached working dirs" or something. Like this:

# Create a separate "checkout" in ~/Temp/mgs/
$ git --git-dir ~/Projects/fboender/multi-git-status/.git --work-tree ~/Temp/mgs reset --hard

I suspect that this is what yadm does under the hood, much like other dotfile managers.

Multi-git-status needs to know both the working dir and the .git dir locations. Otherwise, it cannot give meaningful information on much of the state of a repository. However, there is no link between the two (unless the .git dir is in the working dir), and no way for multi-git-status to figure out their locations.

For example, I can use something like this to match all of the git repositories mgitstatus finds, plus the yadm repo I mentioned: find -L . -maxdepth 3 -type d -name "*.git"

This is already what mgitstatus does at the moment. See line 128. But mgitstatus needs both the .git dir and the working tree.

I currently don't see a very user-friendly way on the commandline for the user to provide a mapping between where the .git files are located and where the working tree is for multiple repositories. Unless I add something like a configuration / mapping file. Perhaps something like this:

# <work tree> [.git path]
/home/fboender/Temp/mgs /home/fboender/Projects/fboender/multi-git-status/.git
/home/fboender/foo /home/fboender/Projects/fboender/foo/.git

That's a bit of a departure from the way mgitstatus works now. I'm not sure it's worth it to support such a (I assume) fringe use-case.

abathur commented 5 years ago

Good point. I agree that it's probably an edge-case that doesn't justify significantly complicating anything.

I'll try to find some time to think on/poke at the source.

abathur commented 5 years ago

Had a little time to pick at implementing this directly in command syntax. The basic functionality is pretty simple, but finding logical/syntactical space for it is a little trickier...

Here are the main ways I've thought about it:

  1. Accept additional positional args and treat each pair as a work_tree and git_dir.
    • This keeps the conceptual code change pretty small.
    • But it would block you from adding more positional args, which you might justifiably object to :)
    • I don't recall having seen paired positional args as a pattern before. May be some confusion around communicating it.
  2. Do the same as 1 above, but require a lone -- arg to separate them.
    • This would preserve space for more positional args.
    • -- is already a git syntax idiom, and this does use it in a similar-but-not-identical way.
  3. Make a separate version of the command/script to handle this use-case.
    • Could be an advanced/explicit version that supports all behavior, or just laser-focused on this edge case.
    • Doesn't burden existing syntax or take up space in the potential syntax space.
    • But, keeping it DRY would mean separating parts and generating the existing executable script and a new one.
  4. Use a flag (whatever short/long flag you prefer; I used -x for explicit when I tried this)
    • to indicate a different syntax mode that interprets all positional arguments differently
      • doesn't really fit in with existing arg/syntax patterns, so documenting/communicating/understanding may all be harder
    • supply once per target repo (as many times as desired), and consume the next 2 arguments,
      • the current arg parsing model doesn't square well with this; implementation/diff likely more complex/involved
      • consuming 2 args per flag is a little surprising

Curious how these strike you.