Skip to content

Instantly share code, notes, and snippets.

@mjavadhpour
Last active March 8, 2024 13:33
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mjavadhpour/a140e75882b87d8f3d70f2b0508f21cd to your computer and use it in GitHub Desktop.
Save mjavadhpour/a140e75882b87d8f3d70f2b0508f21cd to your computer and use it in GitHub Desktop.

My Git Convention And Style Guide:

This is a Git Style Guide inspired by How to Get Your Change Into the LinuxKernel, the git man pages and various practices popular among the community.

Table of contents

  1. Branches
  2. Commits
  3. Changelog
  4. Merging
  5. Release process
  6. 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"). 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 issue name used for branch name, then you must regard to Quick Legend in issue title.

    Tip: Use the following command while being on "master", to list merged branches:

    $ git branch --merged | grep -v "\*"

Commits

We use conventional commits and you must to tell your users that you adhere to the Conventional Commits specification:

[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
  • 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.

  • Consider these messages as the instructions for what applying the commit will do. Rather than having a commit with the title:

    renamed the iVars and removed the common prefix
    

    Have one like this:

    rename the iVars to remove the common prefix
    
  • Use the imperative, present tense: "change" not "changed" nor "changes".

  • Don't capitalize first letter in commit title.

  • No dot (.) at the end.

    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:

      # 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:

      # 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):

      feat(Initializer): Initializers use ManagerRegistry
      
      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`.
      
      - 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
      
      Fixes: #1234, #4321
      See also: #12, #34
      

      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:

      $ 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:

      <type>(<scope>): <short description>
      
      [optional body]
      
      [optional footer]
      
      • <scope> is fully depend on your project and can be anything specifying place of the commit change. for example if you work on the Android project maybe your scope is: <manifest|drawerLayout|...>. to get fully supported scope in your project please contact to your team manager.
      • In [footer] you can reference the issue that was resolved or closes or related.
    • Short Commit Message:

      Not all Pull Requests require this much information for the commit. In most cases, a more simpler commit convention is enough:

      <type>(<scope>): <short description>
      

      Allowed types:

      • feat: A new feature (refers to MINOR in SemVer)
      • fix: A bug fix (refers to PATCH in SemVer)
      • 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)
      • 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:

      $ git config --global commit.template ~/.git_commit_msg.txt

      Note: We can automatically generate commit message with using Commitizen for contributors. please see Commitizen for contributors

Changelog

Note: We will use Conventional Changelog and Commitizen for contributors to commit our changes in a right way by using angular commit conventions. The Commitizen for contributors will generate our commits in a template that acceptable by Conventional Changelog and help us to no more digging through CONTRIBUTING.md to find what the preferred format is and will generate our CHANGELOG.md automatically.

  • An opinionated approach to CHANGELOG generation using angular commit conventions.

    Note: You can use Standard Version for Automatic versioning and CHANGELOG generation.

    Install:

    $ npm install -g standard-changelog

    usage: your first release: If you're using this tool for the first time and want to generate new content in CHANGELOG.md, you can run:

    $ standard-changelog --first-release

    For normal usage you can execute just:

    $ standard-changelog
  • Install globally:

    $ npm i -g standard-version

    Create package.json in root of your project:

    $ cd my-project
    $ nano package.json

    Then add this folowing json string to package.json:

    {
     "version": "<my-first-version>",
     "description": "<my-description>",
     "scripts": {
        "release": "standard-version"
      }
    }

    Note: Fill <my-first-version> and <my-description> with your own version and description.

    First Release:

    $ standard-version --first-release

    If you typically use npm version to cut a new release, do this instead:

    $ standard-version

    And it will automatically tag and update changelog really nicely.

  • After you install Standard CHANGELOG you can install as simple as running the following command

    $ npm install -g commitizen

    Install your preferred commitizen adapter globally, for example cz-conventional-changelog

    $ npm install -g cz-conventional-changelog

    Create a .czrc file in your home directory, with path referring to the preferred, globally installed, commitizen adapter with run this command in terminal:

    $ echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc

    You are all set! Now cdinto any git repository and use git cz instead of git commit and you will find the commitizen prompt some thing like this image:

    add-commit

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:

      [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:

    # good - ensures that a merge commit is created
    $ git merge --no-ff my-branch
    
    # bad
    $ git merge my-branch

    Useful command:

    $ 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. Commit all your changes
    2. Tag the latest commit with git tag v1.7.0
    3. Update CHANGELOG.md in root of project with standard-changelog
    4. 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 for marking releases or other important points in the history. Prefer 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:

Workflow Diagram

Git Branching Model

@mjavadhpour
Copy link
Author

mjavadhpour commented Oct 19, 2017

It's good idea to use angular validate commit message to validate commits with required template.

@mjavadhpour
Copy link
Author

mjavadhpour commented Oct 19, 2017

Conventional commits
regex pattern is :

/^(\m*)(?:\((.*)\))?\: (.*)$/

@mjavadhpour
Copy link
Author

@mjavadhpour
Copy link
Author

@mjavadhpour
Copy link
Author

@mjavadhpour
Copy link
Author

mjavadhpour commented Oct 19, 2017

commitlint to create our own scope and more

@mjavadhpour
Copy link
Author

mjavadhpour commented Oct 19, 2017

semantic-release

Conventional Commits

@mjavadhpour
Copy link
Author

mjavadhpour commented Nov 25, 2017

  • [Suggestion] I think that document most review with this article.

@mjavadhpour
Copy link
Author

@mjavadhpour
Copy link
Author

@mjavadhpour
Copy link
Author

  • [Suggestion] Please review the grunt bump fr bumped version with this mom package. Also, this package can generate the changelog.

@mjavadhpour
Copy link
Author

Mixing of bumpversion + Vincent Driessen's branching model + git flow was accepted and tested.

The changelog should write manually :|

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment