# Nikmodern Git Convention And Style Guide: This is a Git Style Guide inspired by [*How to Get Your Change Into the LinuxKernel*](https://kernel.org/doc/html/latest/process/submitting-patches.html), the [git man pages](http://git-scm.com/doc) and various practices popular among the community. ## Table of contents 1. [Branches](#branches) 2. [Commits](#commits) 2-1. [Messages](#messages) 2-2. [Template](#template) 3. [Changelog](#changelog) 4. [Merging](#merging) 5. [Release process](#release-process) 6. [Misc.](#misc) ## Branches * Quick Legend: |Instance | Branch | Description, Instructions, Notes| |---------|---------|-------------------------------------| |Stable | stable | Accepts merges from Working and Hotfixes| |Working | master | Accepts merges from Features/Issues and Hotfixes| |Features/Issues | topic-* | Always branch off HEAD of Working| |Hotfix | hotfix-* | Always branch off Stable| * Conventions: | Description|Good example|Bad example| |------------|------------|-----------| |Choose *short* and *descriptive* names|oauth-migration|login_fix| |Use *hyphens* to separate words|branch-name|branchName, branch name, branch_name| |When several people are working on the *same* feature, it might be convenient to have *personal* feature branches and a *team-wide* feature branch.|feature-a/master, feature-a/maria, feature-a/nick| - | Merge at will the personal branches to the team-wide branch (see ["Merging"](#merging)). Eventually, the team-wide branch will be merged to "master". * Delete your branch from the upstream repository after it's merged, unless there is a specific reason not to. **Required**: If you working with [GitLab Issues Functionalities](https://docs.gitlab.com/ce/user/project/issues/index.html#gitlab-issues-functionalities) issue name used for branch name, then you must regard to [Quick Legend](#Quick-Legend) in issue title. Tip: Use the following command while being on "master", to list merged branches: ```shell $ git branch --merged | grep -v "\*" ``` ## Commits * Each commit should be a single *logical change*. Don't make several *logical changes* in one commit. For example, if a patch fixes a bug and optimizes the performance of a feature, split it into two separate commits. *Tip: Use `git add -p` to interactively stage specific portions of the modified files.* * Don't split a single *logical change* into several commits. For example, the implementation of a feature and the corresponding tests should be in the same commit. * Commit *early* and *often*. Small, self-contained commits are easier to understand and revert when something goes wrong. * Commits should be ordered *logically*. For example, if *commit X* depends on changes done in *commit Y*, then *commit Y* should come before *commit X*. Note: While working alone on a local branch that *has not yet been pushed*, it's fine to use commits as temporary snapshots of your work. However, it still holds true that you should apply all of the above *before* pushing it. * ### Messages * Use the editor, not the terminal, when writing a commit message: ```sh # good $ git commit # bad $ git commit -m "Quick fix" ``` Committing from the terminal encourages a mindset of having to fit everything in a single line which usually results in non-informative, ambiguous commit messages. * The summary line (ie. the first line of the message) should be *descriptive* yet *succinct*. Ideally, it should be no longer than *50 characters*. It should be capitalized and written in imperative present tense. It should not end with a period since it is effectively the commit *title*: ```shell # good - imperative present tense, capitalized, fewer than 50 characters Mark huge records as obsolete when clearing hinting faults # bad fixed ActiveModel::Errors deprecation messages failing when AR was used outside of Rails. ``` * After that should come a blank line followed by a more thorough description. It should be wrapped to *72 characters* and explain *why* the change is needed, *how* it addresses the issue and what *side-effects* it might have. It should also provide any pointers to related resources (eg. link to the corresponding issue in a bug tracker): ```text feat [Initializer] Initializers use ManagerRegistry Fixes: #1234, #4321 See also: #12, #34 Initializers are now passed an instance of `ManagerRegistry` instead of the `Phpcr\Session`. This means that initializers can retrieve both the PHPCR session and the `DocumentManager`. This PR also introduces a requirement that all initializers provide a name which can be used in diagnostics. BC Breaks --------- - The `init` method of the InitializerInterface now accepts a `ManagerResistry` instead of a `PhpcrSession`. The PHPCR session can be retrieved using `$registry->getConnection` and the manager with `$registry->getManager()`; - The first argument to the `GenericInitializer` constructor is now the name of the initializer. Short (50 chars or fewer) summary of changes ``` Ultimately, when writing a commit message, think about what you would need to know if you run across the commit in a year from now. * If a *commit A* depends on *commit B*, the dependency should be stated in the message of *commit A*. Use the SHA1 when referring to commits. Similarly, if *commit A* solves a bug introduced by *commit B*, it should also be stated in the message of *commit A*. * If a commit is going to be squashed to another commit use the `--squash` and `--fixup` flags respectively, in order to make the intention clear: ```shell $ git commit --squash f387cab2 ``` *(Tip: Use the `--autosquash` flag when rebasing. The marked commits will be squashed automatically.)* * ### Template * ###### Commit Message: The commit message should be formatted as follows: ```text [] Fixes: See also: BC Breaks (as required) --------- Deprecations (as required) ------------ ``` * `` is fully depend on your project. for example if you work on the Android project maybe your scope is: ``. to get fully supported scope in your project please contact to your team manager. * ###### Short Commit Message: Not all Pull Requests require this much information for the commit. In most cases, a more simpler commit convention is enough: ```nano [] ``` Allowed types: * **feat**: A new feature (refers to `MINOR` in [SemVer](http://semver.org/)) * **fix**: A bug fix (refers to `PATCH` in [SemVer](http://semver.org/)) * **docs**: Documentation only changes * **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, newline, line endings, etc) * **refactor**: A code change that neither fixes a bug or adds a feature (refers to `MAJOR` in [SemVer](http://semver.org/)) * **perf**: A code change that improves performance * **test**: Adding missing tests * **chore**: Changes to the build process or auxiliary tools and libraries such as documentation generation You can set git template globally with runnig this command: ```shell $ git config --global commit.template ~/.git_commit_msg.txt ``` ## Changelog ## Merging Note: If you are not *project manager* you can skip this step. * **Do not rewrite published history.** The repository's history is valuable in its own right and it is very important to be able to tell *what actually happened*. Altering published history is a common source of problems for anyone working on the project. * However, there are cases where rewriting history is legitimate. These are when: * You are the only one working on the branch and it is not being reviewed. * You want to tidy up your branch (eg. squash commits) and/or rebase it onto the "master" in order to merge it later. That said, *never rewrite the history of the "master" branch* or any other special branches (ie. used by production or CI servers). * Keep the history *clean* and *simple*. *Just before you merge* your branch: 1. Make sure it conforms to the style guide and perform any needed actions if it doesn't (squash/reorder commits, reword messages etc.) 2. Rebase it onto the branch it's going to be merged to: ```shell [my-branch] $ git fetch [my-branch] $ git rebase origin/master # then merge ``` This results in a branch that can be applied directly to the end of the "master" branch and results in a very simple history. *(Note: This strategy is better suited for projects with short-running branches. Otherwise it might be better to occassionally merge the "master" branch instead of rebasing onto it.)* * If your branch includes more than one commit, do not merge with a fast-forward: ```shell # good - ensures that a merge commit is created $ git merge --no-ff my-branch # bad $ git merge my-branch ``` Useful command: ```shell $ git checkout master // change to the master branch $ git merge --no-ff feature-id // makes sure to create a commit object during merge $ git push origin master // push merge changes $ git push origin :feature-id // deletes the remote branch ``` ## Release process Example for version `v1.7.0` 1. Bump the version in `lib/omniauth-saml/version.rb` 1. Update [CHANGELOG.md](CHANGELOG.md) in root of project with `bundle exec conventional-changelog version=v1.7.0 since_version=v1.6.0` 1. Commit all your changes 1. Tag the latest commit with `git tag v1.7.0` 1. Contact the maintainers ## Misc. * There are various workflows and each one has its strengths and weaknesses. Whether a workflow fits your case, depends on the team, the project and your development procedures. That said, it is important to actually *choose* a workflow and stick with it. * *Be consistent.* This is related to the workflow but also expands to things like commit messages, branch names and tags. Having a consistent style throughout the repository makes it easy to understand what is going on by looking at the log, a commit message etc. * *Test before you push.* Do not push half-done work. * Use [annotated tags](http://git-scm.com/book/en/v2/Git-Basics-Tagging#Annotated-Tags) for marking releases or other important points in the history. Prefer [lightweight tags](http://git-scm.com/book/en/v2/Git-Basics-Tagging#Lightweight-Tags) for personal use, such as to bookmark commits for future reference. * Keep your repositories at a good shape by performing maintenance tasks occasionally: * [`git-gc(1)`](http://git-scm.com/docs/git-gc) * [`git-prune(1)`](http://git-scm.com/docs/git-prune) * [`git-fsck(1)`](http://git-scm.com/docs/git-fsck) ## Workflow Diagram ![Git Branching Model](http://f.cl.ly/items/3i1Z3n1T1k392r1A3Q0m/gitflow-model.001.png)