ingydotnet / git-subrepo

MIT License
3.28k stars 271 forks source link

Document intended usage with nested subrepos #629

Open abeforgit opened 3 months ago

abeforgit commented 3 months ago

I'm testing out git-subrepo for our project, which has currently 2 levels of subrepos, like this:

app
|- foo
    |- bar

This works, of course, as it's even simpler than the structure in git-subrepo itself. However what's not fully clear is the intended workflow. An example:

I open the app folder. I make a change in bar. I commit, and now I want to propagate this change.

what should I do?

option 1: git subrepo push foo/bar

This fails with:

Command failed: 'git branch subrepo/foo/bar '.
fatal: not a valid object name: '

option 2: git subrepo push foo and then git subrepo push foo/bar

This fails for the same reason as above

option 3: the only working way I've found

git subrepo push foo
cd ~/repos/foo #this is where the "real" clone is stored
git pull
git subrepo push bar
cd - #back to the top repo
git subrepo pull foo #necessary because the previous push added a commit

Is this the "intended" way? Looking at the .gitrepo files, I think I understand why this is necessary, but I feel like I'm maybe missing something

If not, it might be worth adding this to the README. I can make a pr for that

option 4: just don't

It may be that the intended workflow is to make the changes in the "native" repos, and use way more pulls than pushes? This would also be fine, I just got excited at the possibility to work across projects as if they were a monolithic bundle.

admorgan commented 3 months ago

The expected workflow is option 3.

It may be possible to implement the other options but let me describe some of the design issues.

Option 1, foo/bar may have many changes to bar that haven't been submitted. It would be hard to describe what was going to happen to the user. As you identified earlier git push also creates a commit in foo stating what the parent value is and that would not have been synced to foo causing a disconnect that could get rather difficult to unravel in a number of use cases.

Option 2, It is difficult for our add-on to identify that the push to foo was successful and then allow the push to foo/bar, git just doesn't store that much state. Again the end result would be the same issue as option 1.

I also get scared any time operations have to deal with multiple operations on multiple repositories and there isn't a good roll back path if an issue is discovered "mid flight".

The expected workflow, option 3, is that your project makes changes it needs to foo, including any changes to bar that you need. You push that to foo and the maintainers for foo decide if the changes to bar should be pushed upstream independently. Of course it is pretty common for the bar maintainers to be the same as foo, so it can feel underwhelming that you can't do it all from one place.

I love PRs that help with understanding complex ideas like this and appreciate your help.