mateodelnorte / meta

tool for turning many repos into a meta repo. why choose many repos or a monolithic repo, when you can have both with a meta repo?
MIT License
2.03k stars 95 forks source link

Support DVCS #321

Open pboling opened 1 year ago

pboling commented 1 year ago

πŸš€ Feature Proposal

DVCS, or Distributed Version Control Systems, like git, allow for code to be hosted in a distributed manner. I am now [beginning to replicate][summary] my projects on 2, 3, 4 (more?!?) different source forges. I am also starting to convert at least one of these projects into a "distributed" meta repo using this tool (πŸ›–1, 🧊2, πŸ§ͺ3, πŸ™4!).

My goal is for each sub-project to push to an "all" instead of an "origin", where "all" targets several remote repositories.

Motivation

Without this feature it seems that I'll need to not use most of this project's features and run lots of manual commands on each sub-project.

Example

meta git push all would push to all.

Of course I can already do meta exec git push all... So this feature request is about how to configure the multi-repo'd projects.

Currently we have:

meta project create [folder] [repo]
meta project import [folder] [repo]

I'd like to have a way to run the necessary commands (as in my summary article [already linked][summary]) to setup the "all" remote with many target repos. Perhaps a new command distribute:

meta project distribute [folder (existing project)] [repo (new)] [remote name (default "all")]

And that would run something like this:

cd [folder]
git remote add all [original repo] # See NOTES.1 and NOTES.2
git remote set-url --add --push [remote name] [repo] && \

NOTES:

  1. It would need to determine the original repo URL first, to add it as the first member of "all".
  2. It will be easiest to do this every time distribute is run. If "all" already exists it will just fail that command, as follows:
    ❯ git remote add all git://original/repo.git
    error: remote all already exists.
  3. It will do the wrong thing if you add the original again as a push target, which you need to do only the first time you add a new push target to all. It will add the same push target multiple times.
    
    ❯ git remote add all git@github.com:pboling/require_bench.git
    ❯ git remote set-url --add --push all git://another/repo.git
    # Original has to be added back, because previous command removed it 🀦 
    ❯ git remote set-url --add --push all git@github.com:pboling/require_bench.git
    # Search for Original repo to ensure it is added back as a push target
    ❯ git remote -v | egrep "all\s+git@github\.com:pboling\/require_bench\.git\s+\(push\)"
    all git@github.com:pboling/require_bench.git (push)

First time around, ^ is fine, as the original is a fetch and push target 1x each.

But, the next time around, it doesn't work so well, so you'd need to test if the original repo is already a push url:

❯ git remote set-url --add --push all git://yet-another/repo.git

Somehow detect if the original is already present as a push target, and only add it back if missing.



[summary]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
pboling commented 1 year ago

I set one of the repos in my meta repo linked above as an array with two git repos to see what it would do.

> meta git update
...
/Users/pboling/src/meta/rubocop-lts: command 'git clone git@gitlab.com:rubocop-lts/rubocop-lts.git,git@codeberg.org:rubocop-lts/rubocop-lts.git rubocop-lts' exited with error: Error: Command failed: git clone git@gitlab.com:rubocop-lts/rubocop-lts.git,git@codeberg.org:rubocop-lts/rubocop-lts.git rubocop-lts

That's pretty dense, but the command that ran was:

git clone git@gitlab.com:rubocop-lts/rubocop-lts.git,git@codeberg.org:rubocop-lts/rubocop-lts.git rubocop-lts

And the problem is obviously that it ran a single command with both git repos, instead of the set of commands to add the additional repos after the first as push targets.

patrickleet commented 1 year ago

interesting - wasn't aware you could have multiple push targets for a remote.

meta-project is mostly just executing commands in child processes, so doesn't sound too difficult to create theoretically

pboling commented 1 year ago

git push all is my new favorite thing, and I can push to all my DVCS remotes at once!

pboling commented 1 year ago

Found a sequence of commands that may be helpful. Requires grep and cut, but those are fairly universal on POSIX machines. git remote -v | grep origin | grep fetch | cut -w -f2

Used like this:

❯ git remote -v
all git@github.com:rubocop-lts/meta.git (fetch)
all git@git.sr.ht:~galtzo/rubocop-lts-meta (push)
all git@github.com:rubocop-lts/meta.git (push)
all git@gitlab.com:rubocop-lts/meta.git (push)
all git@codeberg.org:rubocop-lts/meta.git (push)
origin  git@github.com:rubocop-lts/meta.git (fetch)
origin  git@github.com:rubocop-lts/meta.git (push)
❯ orig=$(git remote -v | grep origin | grep fetch | cut -w -f2)
❯ echo $orig
git@github.com:rubocop-lts/meta.git
patrickleet commented 1 year ago

all is just a name though, right? you could set up origin to push to many as well?

pboling commented 1 year ago

Yeah, correct; technically origin is just a name as well, just very common due to it being a default value.