All extensions of the app
directory are subtrees (effectively).
- com_fmns: Faculty Mentoring Networks component (in development). dev âś… prod âś…
- com_partners: Partners component dev âś… prod âś…
- com_publications: Override of HubZero publications component. dev âś… prod âś…
- com_tags: Override of HubZero tags component. dev âś… prod âś…
Note: Needed to include extra installation directory instructions in the composer.json
files so that they install in the mod_
prefix directories.
- mod_partners: Shows partners in grid format. dev âś… prod âś…
- mod_qubes_events: Displays QUBES Happening events, consisting mainly of faculty mentoring networks. dev âś… prod âś…
- mod_qubes_tools: Displays QUBES Tools in grid format (in development). dev ❌ prod ❌
- mod_showcase: Displays static and dynamic billboards in grid format. dev âś… prod âś…
- mod_slider: Displays billboards in slider format (not live on QUBES) dev âś… prod âś…
- plg_content_qubesmacros: Content plugin that contains QUBES macros. dev âś… prod âś…
- plg_projects_publications: Override of HubZero project publications plugin. dev âś… prod âś…
- plg_groups_publications: Publication plugin for groups component. dev ✅ prod ❌
- plg_groups_resources: Override of HubZero resource plugin for groups. This will eventually take over the plg_groups_publications plugin above dev ❌ prod ❌
- plg_groups_usage: Override of HubZero usage plugin for groups. dev âś… prod âś…
- plg_system_menurouter: Prepend menu parent items to generated component URLs and route menu items appropriately. dev âś… prod âś…
- plg_system_subnav: Component/URL to subnavigation mapping dev âś… prod âś…
The vagrant box pulls from this fork of the HubZero CMS. So, if you are developing within the app
directory and do not care about updating the servers (dev
, stage
, qa
, or prod
), you should be able to simply give the following:
git push origin master
Make sure before you push, though, to pull in changes first:
git pull --rebase origin master
Interesting stuff happens only when you want to update the code on the servers.
Note that in the commands below, while we are referring to "subtrees", we are not using the "subtree" scripts bundled with git. This is due to (1) the complete clusterfudge that occurs with history when using subtrees, and (2) the occurrence of the subtree-cache directory which gets HUGE and is never cleaned. Also, going the manual route forces a deeper understanding of git, which overall HAS to be a good thing, right?
Reference for manual subtree commands: Mastering Git subtrees by Christophe Porteneuve.
First, checkout a new branch:
[master]$ git checkout -b <extension>
Filter out the core extension from the history into the new branch:
[extension]$ git filter-branch --subdirectory-filter <path to core extension>
NOTE: Git is yelling about not using this and moving to filter-repo
. Here is what appears to be an equivalent command using filter-repo
:
git filter-repo --subdirectory-filter <path to core extension> --refs=<extension>
You might have to use --force
on these commands, and note that <extension>
is the name of the branch that you just created.
Add the new remote on GitHub:
[extension]$ git remote add <extension> https://github.com/qubeshub/<extension>.git
Push to the new remote repository:
[extension]$ git push -u <extension> <extension>:master
Switch back to the master
branch and follow the instructions in the next section to add in the new remote extension as a subtree to the app
directory.
[extension]$ git checkout master
First, add the remote repository and fetch the repo:
[master]$ git remote add <extension> https://github.com/qubeshub/<extension>
[master]$ git fetch <extension>
Now, pull in the extension repository and put it into the correct subdirectory of app
.
[master]$ git read-tree --prefix=app/<extension dir> -u <extension>/master
<extension dir>
can be
app/components/<extension>
,app/modules/<extension>
,app/plugins/<extension>
,app/templates/<extension>
The previous read-tree
command will not commit the result - we'll have to do that ourselves.
[master]$ git commit -m "Added <extension> as subtree"
This repository is designed so you can code within multiple extensions at once, pushing and pulling from origin
, without having to worry about updating the remote extensions, unless you want to update the code on the servers. This section covers how to do just that. We'll assume we want to update an extension called ext_foo
.
For the code that follows, the [main]$
prompt tells us we are on the main repo (this one), while the [foo]$
prompt tells us we are on the master branch of ext_foo
.
[main]$ git remote
If you don't see it in the list, add it:
[main]$ git remote add ext_foo https://github.com/qubeshub/ext_foo.git
First, fetch
all remote changes.
[main]$ git fetch --all
You could only pull in the repo you want to update, which would just be
[main]$ git fetch <package>
This command will show all commits that touched a specific directory where our package resides (app/ext/foo
).
[main]$ git log --oneline -- app/ext/foo
Grab the hashes for the commits of interest.
[main]$ git checkout -b ext_foo ext_foo/master
There are a few commands that we should be aware of:
git cherry-pick -x <hash>
git cherry-pick -x -n (--no-commit) <hash>
git cherry-pick -x --strategy=subtree <hash>
It is a good idea to look at each commit to see if there was an edit, addition, or deletion, as the addition and deletions will cause some trouble.
For most things, the 2nd command above will work. If you have files that are NOT in the extension of interest, use git rm -r
(recursive for directories).
In this case, you need to use option #2 above. Git doesn't know about these files yet in the package repo, and so it will add it to the package repo in the subdirectory structure of the main repo and then will automatically commit. We need to manually tell git where the files should go:
[foo]$ git cherry-pick -x --no-commit <hash>
[foo]$ git status
...
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: app/ext/foo/<new file #1>
...
All we need to do now is a git mv
for all new files
[foo]$ git mv app/ext/foo/<new file #1> <new file #1>
Finally, copy-and-paste the commit message from the main repository
[foo]$ git commit -m <commit message>
Note: I'm curious of option #3 would help here, i.e. if it does a subtree merge, will it know to strip the app/ext/foo
? See next section note as well.
You might get the following:
[foo]$ git cherry-pick -x <hash>
error: could not apply <hash>... [Commit message here]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
On branch ext_foo
Your branch is ahead of 'ext_foo/master' by xx commits.
(use "git push" to publish your local commits)
You are currently cherry-picking commit <hash>.
(fix conflicts and run "git cherry-pick --continue")
(use "git cherry-pick --abort" to cancel the cherry-pick operation)
Unmerged paths:
(use "git add <file>..." to mark resolution)
added by us: <deleted file #1>
added by us: <deleted file #2>
Just git rm
each file separately and then type git cherry-pick --continue
.
Note: I'm pretty sure we can give strategy options here, such as -Xtheirs
. My impression here is that git sees that the extension has the files, but the main repo does not, and it doesn't know which one to respect. By saying theirs
we are telling git which one to do.
Sometimes a commit with only edits comes across as a deletion. For example,
You are currently cherry-picking commit <hash>.
(fix conflicts and run "git cherry-pick --continue")
(use "git cherry-pick --abort" to cancel the cherry-pick operation)
Changes to be committed:
modified: css/pages/resourceportal.css
modified: css/pages/resourceportal.scss
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
deleted by us: app/templates/bmc/css/pages/variables.scss
First, mv
the file, as the deleted by us
version is the correct version:
mv app/templates/bmc/css/pages/variables.scss css/pages/variables.scss
Note that git mv
won't work as the deleted by us
file is not under version control. Now if you do git status
, you might seen
...
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
deleted by us: app/templates/bmc/css/pages/variables.scss
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: css/pages/variables.scss
...
Strangely, we have to git rm
the app/templates/bmc
file and git add
the modified file for staging.
[foo]$ git rm app/templates/bmc/css/pages/variables.scss
[foo]$ git add css/pages/variables.scss
We can then continue the cherry-picking
[foo]$ git cherry-pick --continue
[foo]$ git push ext_foo HEAD:master
This is a rare operation as the only thing we are tracking in the app directory now are some overrides.
If you want to push changes to dev
, you need to update the app
repository, as the dev
machine has the app
directory added as a subtree. To do this:
git subtree push --prefix=app origin app
This will update the app
branch on GitHub, as long as origin
is set to https://github.com/qubeshub/hubzero.cms
(which it should be).
On the dev
machine, all you have to do now is:
git subtree pull --prefix=app qubeshub app
Note the change of the remote from origin
to qubeshub
. On dev
, origin
is set to https://github.com/hubzero/hubzero.cms
, and qubeshub
is set to https://github.com/qubeshub/hubzero.cms
.
On the Thursday or Friday before QA push, do the following:
git fetch --all
git pull upstream dev
This will pull in the new code into /core
.
Make sure you are in the vagrant directory and run the following commands:
vagrant ssh
cd /var/www/public/core
php bin/composer install
cd ..
php muse migration -f
exit
For the extensions that have overrides, follow the same steps above for updating remote extensions.
After updating the remote extension, we need to merge those commits into the extensions in the app directory on the master branch.
git merge -X subtree=app/<extension directory> -Xtheirs --squash <extension>/master --allow-unrelated-histories
The -Xtheirs
is important and safe, as we effectively want our version in the main repo to mirror the remote extension.
This will pull in ALL commits in the history of the repo into the commit message. Edit the commit file as follows.
Squashed commit of the following:
to
[extension] Squashed commit of the following...
Include all recent commits from the core to app merge. After the oldest more recent commit, delete all the way until the commit info at the end (although these will be stripped as they are just comments - good to reread just to be sure).
Supposing you just did 3 squash merges of updated extensions into the app directory, you now want to merge all of these into one commit by performing an interactive rebase as follows.
git rebase -i HEAD~3
This will put you into an editor and give you something like the following.
pick e43cebab [extension #1] Squashed commit of the following...
pick 56bcce71 [extension #2] Squashed commit of the following...
pick a2b6eecf [extension #3] Squashed commit of the following...
Change this to the following:
pick e43cebab [extension #1] Squashed commit of the following...
squash 56bcce71 [extension #2] Squashed commit of the following...
squash a2b6eecf [extension #3] Squashed commit of the following...
It will then open up the editor again to let you edit the commit message. All commit messages for the three commits will be combined, giving you the option to create a new merged commit message. Make this commit message the following:
[maint] April subtree merge of app extensions
For more info, check out the git docs: https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History
Checkout a clone of upstream/dev
:
git checkout --track -b fix-core-bug upstream/dev
Code the fix and then push the new branch to origin:
git push -u origin fix-core-bug
Then, do a pull request! If you don't want to keep the local and/or remote branch:
git branch -D fix-core-bug // Delete locally
git push -d origin fix-core-bug // Delete remotely (I would wait to delete the remote branch until AFTER pull has occurred)