Skip to content

Project structure

Aleix Mariné Tena edited this page Dec 13, 2021 · 7 revisions

Git

Git is the version system used to maintain the programming part of this project. Some git specific guidelines have been adopted regarding the special meaning of some branches in relation with the information and merging state they are in. These guidelines will provide a more secure way of collaborating to the repository and to keep a more structured history of the version in this project.

Branching

The way in which the branching is performed is the one described in the famous post. This branching model is called git-flow.

Here you can see the commit diagram of a repository following this branching scheme: git flow branching schema

Branch meanings and usage

We permanently have the develop branch and the master branch. These are the main two branches.

develop

develop is like the master branch for the developers contributing in the project. It means that every commit in the develop branch means a major change in the development state. These have to be whole features, whole fixes, whole updates etc. Commits in this branch always come from merges of finished features into the develop branch.

master

master is the main branch of the repository and because of that is the branch that is shown when you feshly clone the repository. Because of that has to be a clean and functional state of the code.

Every commit in the master is equivalent to a version. In the develop branch we can fork from master and can merge into master. Master is never merged against other branches (git pull origin master will never occur while in other branches).

Feature branches

Feature branches are branches used by developers to add new features to the code. They only fork from develop and only merge into develop.

As explained, feature branches may have sub-branches, specially used when more that one developer is working in the same feature at the same time as another developer.

For each feature we will have a single main branch for that specific feature with a representative name (e.g. jetbrains_products_update) and any number of feature sub-branches coming from that feature branch and following an extension of the naming schema applied to the branch (e.g. jetbrains_products_update_links).

Release branches.

We also have the release branches, one for each version in master. This branch forks from develop and merges back into master. It will also be merged back into develop in order to obtain the changes. This branch is used to do the final changes in the develop code before publishing it. This could be fixing minor bugs and adding metadata into the code for the release (such as version number). In our case for example we would autogenerate the documentation of FEATURES.md in this step.

Then, this is merged into the master to create a new release of the software. Also is merged back into develop to have the new fixes.

Hotfix branch

Finally we have the hotfixes branch, which is a branch that forks from master and merges into develop and master. It is a branch used to urgently fix bugs in a current release of the software that cannot wait to go through the develop branch with the usual process to be fixed. Then it is merged back into develop if and only if there is no release branch, otherwise, it is merged into the current release to fix the bug. Then after the release is merged into master, is also merged into develop, so develop branch has also the bugfix.

Commands and implications

Every feature branch and release branch that has been fully merged into develop has to be deleted; Of course, deletion will be only allowed by git when the branch is fully merged and also we are not currently in the branch that we want to delete:

git branch -d FEATURE_BRANCH_NAME  # To delete the local branch
git push --delete FEATURE_BRANCH_NAME  # To delete the remote branch

You may end having gitk (or similar) still showing the remote branches but with

git fetch --prune  

we will update gitk or other views regarding existence of the branches or not.

Tagging

We will use tags to statically point to commits that define a version. By definition each commit in the master branch will be tagged and will represent a version of our software, but we will explain how it is done manually.

First we need to explain how to tag a certain commit. We need to use: git tag -a "TAGNAME" -m "brief message explaining what this version does" SHA1ID_OF_THE_TAGGED_COMMIT

This will tag the commit referenced by the SHA1ID with TAGNAME and the brief message.

To push the tags to the repo we use: git push origin --tags

We can remove tags from teh local repository with: git tag -d TAGNAME

We can also delete tags from the remote server easily: git push origin --delete TAGNAME

Commit message format:

This guideline is originally defined in here. It defines a set of tags to be included in the commit message with a meaning regarding the evolution of the source code. This allows us to create a CHANGELOG.md file easily, by using own-defined tags in the commit message.

We adapt this guideline by defining:

Types of changes

  • ADDED: For commits that progresses towards a feature but do not complete it.
  • FINISHED: For commits that finish a feature, when is tested and ready to use.
  • UPDATED: For commits that updates a finished feature such as a version update or changing a fallen link.
  • CHANGED: For commits that change the implementation of a functionality but not the functionality itself.
  • REMOVED: For removed features or deprecations.
  • FIXED: For changes in the code that fix a bug or issue.

Format

For a short message that only includes tag and title we can use: git commit -am "TYPE_OF_CHANGE: Commit title with a complete sentence."

Notice the ":" and the space after the initial tag in the commit message: git commit -am "FIXED: Title after : and the space"

For a long message that includes tag, title and extended description we will use the command:

git commit -am "TYPE_OF_CHANGE: Commit title with a complete sentence. 

Optionally tell other things in this extended description that you want to explain about this commit. 
It can be many lines. Even an enumeration:
- like this.
- and this.
"

Notice the blankline in the long format between the title and the extended description.

For a non-changelog commit that only has extended description use:

git commit -am "
Message in commit that do not have a tag because we do not want to include them in the changelog
"

Notice how the first line is blank in order to not include it in the changelog because it does not have a tag. TODO for each commit:

  • Commit often: keep "small" commits with localized changes: Each commit has to be simple and reflect its title. Is preferable doing many ADDED commits than one single FINISHED. Version history is the major purpose of git.
  • Each commit needs a limited scope. Try to keep the number of modified files to the minimum for each commit. Changes withing a commit have to be related to each other. If unrelated changes have to be performed, commit your changes and put these unrelated changes in a new commit.
  • Do not repeat the commit message. If you have nothing to say is preferrable that you upload an empty commit or a non-changelog commit as defined above.
  • Keep lines of commit messages under 120 characters.
  • Commit following these rules.
  • If you did not fully understand them for your specific case, reread this guide.
  • Do not keep work in your local machine, always keep work in sync with the server.
  • Push only if you are 100 % sure of your changes specially regarding merging state. You are free of adding all the text files you need and doing experimental changes in feature branches.
  • You can ammend your commits locally by using git commit --ammend -am "NEW_COMMIT_MESSAGE". This can not be done when the commit has already been pushed to the server.
  • If nonetheless you did push trash I have something against you and I hate you.

CHANGELOG.md generation

Let's define two arbitrary consecutive tags, tag_A and tag_B. In each release we would like to obtain the commit messages with the right format that have been pushed to the server between tag_A and tag_B. We can do this by using the command:

git log 'tag_A'...'tag_B' 

By adding other modifiers and specifying the tags we can use this command to generate a changelog:

git log --color --decorate --oneline --pretty=format:"%C(auto)%h %d %s (%aN)" 'v0.11.0'...'HEAD' --grep="CHANGED: " --grep="ADDED: " --grep="UPDATED: " --grep="FIXED: " --grep="REMOVED: "

With a little more tweaking we could integrate this line in a CI to generate the CHANGELOG.md file on each commit into the master branch, prepending a changelog of this version to all the previous changelogs:

echo -e "CHANGES IN ACTUALVERSION: \n $(git log --color --decorate --oneline --pretty=format:"%C(auto) %d %s" 'PREVIOUSVERSION'...'ACTUALVERSION' --grep="CHANGED: " --grep="ADDED: " --grep="UPDATED: " --grep="FIXED: " --grep="REMOVED: ")\n$(cat CHANGELOG.md)" > CHANGELOG.md 

We obtain a text similar to this:

d282d22  (HEAD -> master, origin/master, origin/HEAD) ADDED: Dependencies of zoom and meld, (in the end i had to recompile lib gtk source view 3 in order to make meld work) (AleixMT)
cd32379  UPDATED: A table of contents have been added to README.md (Axlfc)
43fefc3  UPDATED: gitk new dependency (unifont) (Axlfc)
5111b0d  UPDATED: Prettifying README.md Updating Tux image (Axlfc)
85bff3d  UPDATED: Dependency of meld libgtkviewsource (AleixMT)
8952f7d  ADDED: gitk to the iochem wrapper (AleixMT)
88cf80c  CHANGED: Added autostart behaviour to copyq and guake (AleixMT)
49dd754  FIXED: Missing packagename property in nemo feature, also removed wikit and npm from iochem wrapper (AleixMT)
283d273  UPDATED: Dependencies of virtualbox. added fix broken before usages of package managers (AleixMT)
e40bfe3  FIXED: Bug in clonerepository installation type. There was an rm missing for avoiding collisions (AleixMT)

Semmantic versioning

We do use semmantic versioning as defined in here.

Given a version number MAJOR.MINOR.PATCH, increment the:

MAJOR version when you make incompatible API changes, MINOR version when you add functionality in a backwards compatible manner, and PATCH version when you make backwards compatible bug fixes. Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.