NOTE: This page is a work-in-progress
Commit Messages
===
Here is a nice article on writing commit messages in general: https://chris.beams.io/posts/git-commit/
The article highlighted seven points, listed as follows:
1. Separate subject from body with a blank line
2. Limit the subject line to 50 characters
3. Capitalize the subject line
4. Do not end the subject line with a period
5. Use the imperative mood in the subject line
6. Wrap the body at 72 characters
7. Use the body to explain what and why vs. how
While these rules are not in any way enforced by git, I suggest everyone to try to follow them whenever possible. The article contains some good explanations on the reasoning behind these rules.
Some editors (e.g. `vim`) has built-in formatting tools and highlighting to help with formatting the commit messages.
KDE-specific Commit Keywords
---
The KDE git server contains commit hooks to perform actions when certain keywords are detected in the commit message. They are listed on this two pages: https://community.kde.org/Infrastructure/Git/Hooks#Keywords, https://community.kde.org/Policies/Commit_Policy#Special_keywords_in_GIT_and_SVN_log_messages
The most-used keywords are:
- `BUG: <bug number>` and `CCBUG: <bug number>`, where `<bug number>` is the bug number on [[ https://bugs.kde.org/ | the KDE Bugzilla ]]. Having either of these keywords will post a comment on the referenced bug, linking the bug to the commit. In addition, the `BUG` keyword will close the referenced bug as FIXED, while `CCBUG` does not.
- `CCMAIL: <email address>` will send a mail about the commit to the listed `<email address>`. It is often used as `CCMAIL: kimageshop@kde.org` to notify the mailing list on huge changes.
- `Differential Revision: https://phabricator.kde.org/DXXXX`, where `DXXXX` is the Differential revision number. Having this keyword with the right URL will: (1) close the referenced revision and (2) update the revision diff to the actual changes in the commit.
- While not a keyword, I advocate using `Maniphest Tasks: TXXXX`, where `TXXX` is the Mahiphest task number, to help linking between the relevant Maniphest task and the commit. This is the keyword used by the Arcanist tool when it creates a commit.
These keywords should be placed at the end of the commit message, separated from the main commit message with an empty line. Each keyword has to be placed at the start of a new line.
Fetching Updates from Remote
===
//Never// perform a plain `git pull` (unless you set the [[ https://git-scm.com/docs/git-config#git-config-pullff | git config `pull.ff = only` ]] on git 2.x). If you have pending local commits on the current branch, doing a plain `git pull` will automatically create a merge commit, which adds clutter to the commit history. Instead, consider using one of the following commands depending on the situation:
- **`git pull --ff-only`**: This command fetches the updates from the remote, then applies them to the local branch only if they can be fast-forwarded, i.e. you don't have pending local commits on the branch. This is for when you just want to fetch updates and apply them if possible. (Note: this is the behaviour of `git pull` if the config `pull.ff = only` is set.)
- **`git pull --rebase=preserve`**: This command fetches the updates from the remote, then performs a rebase while preserving merge commits. You really should only use this when you know what [[ https://git-scm.com/docs/git-rebase | `git rebase` ]] does. Specifying `preserve` is especially important if you have just merged a feature/topic branch, or otherwise your whole branch will be rewritten atop of the updated branch and you lose the merge commit. Because of this, I recommend `git pull --rebase=preserve` over `git pull --rebase`
- **`git fetch origin --prune`**: This command fetches the updates and clean up references to deleted branches. The remote refs in the form of `origin/<branch name>` will be updated. After this, you can manually perform **`git merge --ff-only origin/<branch name>`** to achieve the same effect of `git pull --ff-only`, or **`git rebase --preserve-merges`** for the effects of `git pull --rebase=preserve`.
(The above assumes the remote is named `origin`, but if you somehow have a different remote name, you probably already know what you're doing.)
Branches
===
When to Use Branches
---
You can actually use a branch for everything, from temporary changes to small bugfixes to huge features. The important part is how to incorporate the changes back to the `master` branch (or other main branches). You can even ditch the branch if it's not useful. I tend to make commits directly on master only if I would immediately push the change afterwards.
Branch Naming
---
For branches that is to be pushed to the central KDE/Krita repository, branch names should be in the form of `<your-first-name>/<topic-name>`, or `<your-first-name>/TXXXX-<topic-name>` where `TXXXX` is the Maniphest task number. Branch names should be in lowercase (except for the `T` in the Maniphest task number and the `D` when referring to a Differential revision. Use hyphens (`-`) in place of spaces for the topic name. (`<your-first-name>` doesn't always have to be your first name in full, but please ask Boud before deciding on something weird.)
Bringing In the Changes by Rebasing
---
If the changes doesn't warrant a merge commit, it's better to not make it. You can rebase your branch atop of `master` and fast-forward `master` onto your branch. While being on your local branch, perform these commands:
1. `git fetch origin master` to fetch the latest changes on the master branch
2. `git rebase origin/master` to rebase your current branch atop of the remote master branch (you can add the flag `-i` to perform an interactive rebase to edit the commits if you want)
3. Resolve conflicts if needed, and run `git rebase --continue` after fixing them
4. `git fetch . HEAD:master` to move your local master branch to your current HEAD (the tip of your rebased branch)
5. `git checkout master`
After that, verify that the rebase is done correctly by checking the git log and making sure it works. You can then push the changes.
Note: Do not rebase a branch that has been shared on the central KDE/Krita repository, unless it is discussed and agreed upon.
Actually, if it is small enough I bet nobody would mind... but still, try to avoid doing this.
Merging a Feature/Topic Branch
---
Git merges by merging two parents (or more, but it's rarely done). The order of the parent is important -- avoid foxtrot merges: https://developer.atlassian.com/blog/2016/04/stop-foxtrots-now/
You should always checkout master before performing the final merge of a feature/topic branch.
Note: it is fine to merge master into your branch periodically, but don't do it when you are about to merge the branch back into master.
A typical merge workflow would look like this:
1. `git fetch origin master:master` to fetch the latest changes on the remote master branch and apply them to the local master branch
2. `git checkout master`
3. `git merge --no-ff <branch-name>`: Using `--no-ff` would make sure master won't fast-forward to a foxtrot merge... actually, if you already have a foxtrot merge in place, please redo the merge. (There is a [[ https://stackoverflow.com/questions/25265528/how-do-i-swap-the-order-of-two-parents-of-a-git-commit/36528357#36528357 | command that would make a new commit by switching the two parents of your existing commit ]], but I don't know if it really works.)
4. Resolve conflicts if needed.
5. Add a descriptive message body to your merge commit introducing the feature/change, and add relevant keywords if needed. (Git should automatically show an editor for it, but if it doesn't because you're running an outdated version of Git, run `git commit --amend` to edit the message, and remember to add `--edit` to the git merge command next time.)
After making sure stuff still works, you can push the changes.
At the end, you should also delete your merged branch, both locally and remotely:
1. `git branch -d <branch-name>`
2. `git push origin --delete <branch-name>`