+71
Completed

subtree support [SG-9149]

Marc Strapetz 8 years ago updated 2 years ago 21

Support for "git subtree" command (add, pull, push, merge, split) and its specific commit layout

Missing Git feature

Answer

+1
PINNED
Started

I have now uploaded 20.2 preview build 16021 which comes with following subtree-related features:

SG-9149: Branches: distinguish between allowed and not allowed cross-subtree commands

SG-9149: Journal: distinguish between allowed and not allowed cross-subtree commands

SG-9149: Log: distinguish between allowed and not allowed cross-subtree commands

SG-9149: Cherry-Pick honors subtrees

SG-13690: Subtree: reset command

SG-13685: Subtree: "subtree split" command

SG-13686: Subtree: "subtree merge" command

SG-13693: Subtree: denote subtree refs in Log Graph, Journal and Branches view

Note that most of the functionality requires that a subtree had been initialized with "git subtree add", in order to have meta data present in the initial subtree merge commit message, like:

git-subtree-dir: src/project
git-subtree-mainline: e7f09673067cd094778ed6089c8d4fe0756e73ca
git-subtree-split: 4dffc803a8f86d75d64c26fa5836c240048c9ebb

The display of subtrees is kept really simple, by just denoting subtree Branches and Log Graph commits by ♣. This is very close to Git's core subtree design and should be sufficient for most users of a subtree-enabled repository which shouldn't be interested in the presence of subtrees at all. The only visual difference for them will be ♣ symbols for subtree-merges in the Log Graph. We could even hide them by default as long as there is no .git/subtree-cache folder present. Still, subtree-related logic, like merging or cherry-picking from subtrees, will work.

Those (few?) users which actually work with subtrees can add the corresponding subtree repository as additional remote and thus will get more subtree-related functionality in the Branches view.

The problem with a dedicated "Subtrees"-category (like "Features" or "Local Branches") is that it's orthogonal to SmartGit's current local-remote-branch categorization and would raise several questions.

IMHO, for core subtree operations, there is now just "git subtree add" missing. I'm wondering how the GUI could look like here:

- Should it be a simple operation which can be executed on any selected branch to add it as subtree, like Subtree Merge?

- Should it be more like the Submodule Add wizard?

+5

For me, this is the one missing feature preventing SmartGit from being the Ultimate Git GUI.

Hello all!


Subtree is particularly useful when working with Roots, a powerful Wordpress framework.

Documentation for Roots & its subprojects recommends installing by pulling the git repo... and deleting the .git folder. That's a shame, because we lose the power of git and every update equates to a fresh install.


The particular about this environment is that we pull Trellis, Bedrock & Sage not as dependencies, but as source the we modify. I e.g. added more steps to deploy additional software on the server. Yet we want to receive diff updates on the code, which is not possible by cutting the link to the original repos. So it makes sense to keep the entire code in a single repository. We only need to manage the path where each sub-repo is checked out, as they do not live in different subfolders.


Submodules do not work for this use case, as explained. Subtrees are an excellent tool though.

They are set up by (e.g. Sage deep down the tree):

git subtree add --prefix=site/web/app/themes/sage sage master -m "Add Sage subtree"


Good news is, once subtrees are set up through command-line, they are transparent to Smartgit! Merging updates from upstream into each respective subtree works like a charm. We only need to resolve merge-conflicts created by our own edits. The SmartGit interface does most of the work (which it could not if we had cut the link with upstream).


Sometimes the subtree path goes missing. I do not know where the error comes from yet, but that would probably be solved by a SmartGit implementation.

Please implement setting up subtrees in Smartgit, as you do for submodules and git-flow. To the looks, only the install step is missing, so it is a relatively small workload.

Thanks!

Some additional reading to help with implementation:

+1

Are there plans to make this happen in SmartGit? We just started using subtrees at work and have a bunch of SmartGit licenses here. Most of my colleagues are no "consoleros" and it would make my live as maintainer much easier if a GUI interface to upstream subtree repos would be in SmartGit.

+1

What commands you miss most?

When merging with the current Smartgit Merge, i.e. `git merge` without `--strategy`, sometimes, changes in certain files that lie in a subtree's root directory end up creating the file in our repository's root directory. Files in subtrees' sub-directories never created this issue and already properly merge.

git merge --strategy subtree ORIGIN/BRANCH

avoids this issue. Nothing else seems needed for merge to work.

Two more helpful links:

https://stackoverflow.com/questions/32407634/when-to-use-git-subtree

https://github.com/git/git/blob/master/contrib/subtree/git-subtree.txt

Did you use "git subtree add" command to initialize the subtree? If so, there should be at least an initial subtree merge commit containing meta information about the subtree, like:

git-subtree-dir: src/project
git-subtree-mainline: e7f09673067cd094778ed6089c8d4fe0756e73ca
git-subtree-split: 4dffc803a8f86d75d64c26fa5836c240048c9ebb

Based on this information, SmartGit can infer the subtree prefix and invoke "git subtree merge --prefix=<prefix>" which internally results in a "git merge -Xsubtree=<prefix>". This seems to be safer than "git merge -s subtree" which has to guess about the prefix and could fail.

Did you use "git subtree add" command to initialize the subtree? If so, there should be at least an initial subtree merge commit containing meta information about the subtree, like:

git-subtree-dir: src/project
git-subtree-mainline: e7f09673067cd094778ed6089c8d4fe0756e73ca
git-subtree-split: 4dffc803a8f86d75d64c26fa5836c240048c9ebb

Based on this information, SmartGit can infer the subtree prefix and invoke "git subtree merge --prefix=<prefix>" which internally results in a "git merge -Xsubtree=<prefix>". This seems to be safer than "git merge -s subtree" which has to guess about the prefix and could fail.

Yes, I did initialize with `git subtree add` and the meta-information is present.

Smartgit's output reads `git.exe -c "credential.helper=C:/Program\ Files/SmartGit/lib/credentials.cmd" merge --no-ff <subtree-origin>/master`. This  does not look like it uses `git subtree`.

I didn not know `git merge -s subtree` was guessing. In any case it never guessed wrong.

Is anyone using subtrees to sync back and forth between your main repository and the subtree, i.e. a combination of "git subtree merge" and "git subtree split"? Which exact commands/parameters are you using here?

+1
PINNED
Started

I have now uploaded 20.2 preview build 16021 which comes with following subtree-related features:

SG-9149: Branches: distinguish between allowed and not allowed cross-subtree commands

SG-9149: Journal: distinguish between allowed and not allowed cross-subtree commands

SG-9149: Log: distinguish between allowed and not allowed cross-subtree commands

SG-9149: Cherry-Pick honors subtrees

SG-13690: Subtree: reset command

SG-13685: Subtree: "subtree split" command

SG-13686: Subtree: "subtree merge" command

SG-13693: Subtree: denote subtree refs in Log Graph, Journal and Branches view

Note that most of the functionality requires that a subtree had been initialized with "git subtree add", in order to have meta data present in the initial subtree merge commit message, like:

git-subtree-dir: src/project
git-subtree-mainline: e7f09673067cd094778ed6089c8d4fe0756e73ca
git-subtree-split: 4dffc803a8f86d75d64c26fa5836c240048c9ebb

The display of subtrees is kept really simple, by just denoting subtree Branches and Log Graph commits by ♣. This is very close to Git's core subtree design and should be sufficient for most users of a subtree-enabled repository which shouldn't be interested in the presence of subtrees at all. The only visual difference for them will be ♣ symbols for subtree-merges in the Log Graph. We could even hide them by default as long as there is no .git/subtree-cache folder present. Still, subtree-related logic, like merging or cherry-picking from subtrees, will work.

Those (few?) users which actually work with subtrees can add the corresponding subtree repository as additional remote and thus will get more subtree-related functionality in the Branches view.

The problem with a dedicated "Subtrees"-category (like "Features" or "Local Branches") is that it's orthogonal to SmartGit's current local-remote-branch categorization and would raise several questions.

IMHO, for core subtree operations, there is now just "git subtree add" missing. I'm wondering how the GUI could look like here:

- Should it be a simple operation which can be executed on any selected branch to add it as subtree, like Subtree Merge?

- Should it be more like the Submodule Add wizard?

I would love to try out the new features, but Get latest build does not get me past 20.1.2 #15161

To get the SmartGit 20.2 preview, please download it from https://www.syntevo.com/smartgit/preview/ and use Help | Check for Latest Build there.

As of 20.2 preview 1 #16034, I do not see any functional improvement regarding subtrees:

- Remote > Subtree > Merge / Split / Reset are never clickable, whichever commit or branch I select

- Previously, subtree merges would result in commit messages e.g. Merge remote-tracking branch 'sync-script/master' into staging, now they read Merge commit 'c73651ff26e1ba8f3d2629666a3be81e423ba454' into staging, which is useless

- On proper subtrees, the ♣ shows up only on the subtree commit right before a subtree merge, not on the merge itself.

- https://github.com/roots/trellis never had subtrees, but certain branches still show ♣

- repositories that once were subtrees and are now living alone are still recognized as subtrees, which make Smartgit refuse to merge into root…

> - Remote > Subtree > Merge / Split / Reset are never clickable, whichever commit or branch I select

They will only be applicable if a commit belonging to a subtree has been selected, i.e. a commit denoted by ♣ or any of its ancestors. Why? All these commands require a prefix which is uniquely defined through the selected commit. Also, some of these commands require an additional ref, e.g. Split. Hence, the easiest way is to invoke Split from the context-menu for a ref in the Log Graph.

> - Previously, subtree merges would result in commit messages e.g. Merge remote-tracking branch 'sync-script/master' into staging, now they read Merge commit 'c73651ff26e1ba8f3d2629666a3be81e423ba454' into staging, which is useless

As you can see in the Output view, SmartGit is now executing something like:

$ git subtree merge --prefix=sub refs/remotes/subtree/master 

It seems this command does not preserve the ref name. I agree that it should, but this is rather a shortcoming of "git subtree" itself.

> - On proper subtrees, the ♣ shows up only on the subtree commit right before a subtree merge, not on the merge itself.

Right, this is intended. It could show up on the subtree merge instead, but we want to denote subtree heads which are not yes merged and using ♣ for main repository sub-tree merges and actual subtree commits is slightly inconsistent. To me it's more reasonable that you can rely on ♣ to always point to a subtree commit.

> - https://github.com/roots/trellis never had subtrees, but certain branches still show ♣

Where can you see the ♣? I can only see ⚷ symbols which denote signed commits.

> - repositories that once were subtrees and are now living alone are still recognized as subtrees, which make Smartgit refuse to merge into root…

Can you please provide a test repository illustrating the problem?

Completed

SmartGit 20.2 preview build 16062 now also includes RemoteSubtree - Add. Also, the internal detection of subtree commits has been improved.

+1

Your documentation for subtrees (https://docs.syntevo.com/SmartGit/Latest/Subtrees.html) does not mention Pull to update the subtree from its remote, nor could I find anything in the UI.  I ended up doing directly with Git:

git subtree pull --prefix <local folder> <remote repository> <branch>

This seems like a pretty fundamental operation and it would be nice to be able to do it from SmartGit.

Subtrees are just remotes, hence fetching is straight-forward. I have updated the docs. Given the remaining operations (especially merge), does this make the workflow clear now? If not, please also consider to Propose Changes to the docs directly.