Git commit message conventions
The first line:
- is a summary (not just an indication of the topic)
- <= approximately 50 characters
- is imperative
- is followed by a blank line
- does not end with a period
- the first word is one of the following (most of these can be used as the imperative verb too, except 'perf' and 'aux'):
- 'add' to add a new feature or behavior
- 'cut' to remove an existing feature or behavior
- 'mod' for a modification to existing behavior or feature (this can encompass both 'add' and 'cut')
- 'do' or 'dont' for a major change in behavior (not so much 'feature' addition and subtraction, but rather 'behavior' change)
- 'fix' to fix a bug
- 'doc' for documentation changes (includes also source code comments, formatting, identifier renaming, or very minor LOCAL changes to code to make it easier to read)
- 'reorg' to reorganize code without changing behavior
- 'fmt' to change code formatting
- 'perf' to improve performance without changing behavior
- 'tst' to add tests
- 'aux' for changes to the build process or auxiliary tools and libraries such as documentation generation, or changes to licensing files etc
- 'bump' to increase the version of something eg a dependency
- 'start' and 'stop' to mark the beginning and end of a transient change, eg a feature flag (which is abbreviated ff)
- 'checkpoint' for a checkpoint commit (one that you are doing in the middle of working on something, that you plan to squash later).
There is a blank line in between the first line and the rest.
The rest is word-wrapped to 72 characters (EXCEPT for quoted material that has a specific line format). The rest explains what and why, but not how.
Sources: [1] [2] [3] [4]
Git Workflow
Mostly https://speakerdeck.com/ewoodh2o/release-management-git-workflow
(todo summarize that here)
In addition:
DEVELOP and MASTER
Categorize Git repos into 'personal' and 'common'. Either may be 'public' in the sense that the public can see their contents, and either may or may not be dictatorially controlled by one person.
Each project has at least one common repo (call it 'origin'), and at least two branches within this repo, DEVELOP and MASTER (or, perhaps some projects have DEVELOP and MASTER in two different repos; in this case you may want to call them DEVELOP and PRODUCTION instead).
DEVELOP: Nothing gets into develop unless (a) it appears not to break the build, and (b) it is definitely going into the next release. Ideally, at any time it should be possible to deploy from DEVELOP; however there's some room for error here. If something is merged to DEVELOP and it breaks the build, under most circumstances the merge should be reverted, rather than trying to make a series of hotfixes to DEVELOP or MASTER.
MASTER: MASTER is ALWAYS ready to be deployed/released. It should be OK for an automated script to pull from MASTER and deploy that at any time, without asking a human if that's a good idea. There may be some QA between DEVELOP and MASTER. Any crazy production hotfixes are committed to MASTER.
Some projects have other common repos, and many projects have personal repos.
When to rebase
DO rebase your personal repo off of DEVELOP frequently, and especially just before submitting a merge/pull request, eg using 'git pull --rebase'
DO use rebase to clean up history in your personal repos before requesting/permitting a merge. You are free to rebase anything in a personal repo at any time, with the following exception:
DON'T rebase any commits for which you have given permission to merge into a common repo, or anything that you have given permission to be merged into someone else's personal repo, unless you have an agreement with the owner of the other repo to make sure it doesn't ever get into a common repo. (A merge or pull request is implicitly giving permission)
DON'T rebase anything in common repos. Merge upstream, don't rebase off of it.
Don't merge from personal repos without permission
DON'T merge anything from a PERSONAL repo into a COMMON repo without the permission of the personal repo owner (because if they rebase after you merge, there is a problem). (clearly, you CAN merge from any public repo whose license is compatible with yours; it's just not recommended).
DON'T even merge from someone else's personal repo into your own without persmission, unless you plan to make sure the result never gets into a common repo.
Versioning
http://semver.org/
Sources
[5] [6]
todo
toread: https://wiki.openstack.org/wiki/GitCommitMessages
clean up 'misc', below
to test each commit when rebasing: git rebase -x 'make test'
- git >= 2.9 only
misc
?: if you are the lowest hierarchical level in a tree of development branches (i.e. a single person's working branch), then always rebase when you pull from higher levels of the hierarchy. If, however, you are not the lowest level (you are someone else's upstream), then merge.
- to pull, if you are at the lowest hierarchical level (you are not anyone else's upstream, and others are not pulling from you, or at least not much) and you are pulling from a higher hierarchical level: git pull --rebase
- equivalent if you are getting changes from a local branch: git rebase BRANCH
- to pull, otherwise: git pull
- equivalent if you are getting changes from a local branch: git merge BRANCH
- if "git rebase" screws things up and you want to go back to the way it was before: git reset --hard ORIG_HEAD
- if "git rebase" screws things up and you want to save a ref to te way things were before: git branch name_of_branch_to_save_prior_state_in ORIG_HEAD
- to list branches: git branch
- to switch branches: git checkout BRANCH
- to copy changes from another branch into your working directory: git checkout BRANCH -- .
- to "save a copy" of current state as a branch (but not change to the new branch): git branch NEW_BRANCH_NAME
- to branch off (same as previous but also change to new branch): git checkout -b NEW_BRANCH_NAME
- to throw out the index and working directory and revert them to a clean state: git reset --hard
- to throw out the index and working directory and revert them to a clean state and discard last commit: git reset HEAD^
- to throw out the index and working directory and revert them to a clean state and discard last two commits: git reset HEAD^^
- to undo last git reset: git reset ORIG_HEAD
- to delete a branch: git branch -D BRANCH
- to point the current branch at another commit: git reset COMMIT
- to point the current branch at another commit and throw out index, working directory changes: git reset --hard COMMIT
- to diff between a master (which has moved on since the common ancestor) and a branch, git diff master...BRANCH (git diff would make it look like BRANCH is subtracting all the stuff master added since the common ancestor)
a description of a (non-Git) workflow for developing Chrome: https://medium.com/@aboodman/in-march-2011-i-drafted-an-article-explaining-how-the-team-responsible-for-google-chrome-ships-c479ba623a1b summary of that link:
- don't have feature branches, work on trunk (single engineers can still have local development branches on their personal machines, however)
- there are maintenance branches for each release, but the actual fixes are made on the trunk and then cherry-picked onto the maintenance branch. There is not a team of developers who have to just maintain the maintainence branch.
- feature toggles are runtime, not compiletime
- lots of automated tests. Revert any commit that fails any test or causes any problem.
- they release often
- they refactor a lot
- they try to almost never make local changes to their dependencies; they try to get the changes into upstream, and they pull nightlies or somesuch from upstream every day
links
See also [7]