| gitworkflows(7) | |
| =============== | |
| NAME | |
| ---- | |
| gitworkflows - An overview of recommended workflows with Git | |
| SYNOPSIS | |
| -------- | |
| [verse] | |
| git * | |
| DESCRIPTION | |
| ----------- | |
| This document attempts to write down and motivate some of the workflow | |
| elements used for `git.git` itself. Many ideas apply in general, | |
| though the full workflow is rarely required for smaller projects with | |
| fewer people involved. | |
| We formulate a set of 'rules' for quick reference, while the prose | |
| tries to motivate each of them. Do not always take them literally; | |
| you should value good reasons for your actions higher than manpages | |
| such as this one. | |
| SEPARATE CHANGES | |
| ---------------- | |
| As a general rule, you should try to split your changes into small | |
| logical steps, and commit each of them. They should be consistent, | |
| working independently of any later commits, pass the test suite, etc. | |
| This makes the review process much easier, and the history much more | |
| useful for later inspection and analysis, for example with | |
| linkgit:git-blame[1] and linkgit:git-bisect[1]. | |
| To achieve this, try to split your work into small steps from the very | |
| beginning. It is always easier to squash a few commits together than | |
| to split one big commit into several. Don't be afraid of making too | |
| small or imperfect steps along the way. You can always go back later | |
| and edit the commits with `git rebase --interactive` before you | |
| publish them. You can use `git stash push --keep-index` to run the | |
| test suite independent of other uncommitted changes; see the EXAMPLES | |
| section of linkgit:git-stash[1]. | |
| MANAGING BRANCHES | |
| ----------------- | |
| There are two main tools that can be used to include changes from one | |
| branch on another: linkgit:git-merge[1] and | |
| linkgit:git-cherry-pick[1]. | |
| Merges have many advantages, so we try to solve as many problems as | |
| possible with merges alone. Cherry-picking is still occasionally | |
| useful; see "Merging upwards" below for an example. | |
| Most importantly, merging works at the branch level, while | |
| cherry-picking works at the commit level. This means that a merge can | |
| carry over the changes from 1, 10, or 1000 commits with equal ease, | |
| which in turn means the workflow scales much better to a large number | |
| of contributors (and contributions). Merges are also easier to | |
| understand because a merge commit is a "promise" that all changes from | |
| all its parents are now included. | |
| There is a tradeoff of course: merges require a more careful branch | |
| management. The following subsections discuss the important points. | |
| Graduation | |
| ~~~~~~~~~~ | |
| As a given feature goes from experimental to stable, it also | |
| "graduates" between the corresponding branches of the software. | |
| `git.git` uses the following 'integration branches': | |
| * 'maint' tracks the commits that should go into the next "maintenance | |
| release", i.e., update of the last released stable version; | |
| * 'master' tracks the commits that should go into the next release; | |
| * 'next' is intended as a testing branch for topics being tested for | |
| stability for master. | |
| There is a fourth official branch that is used slightly differently: | |
| * 'seen' (patches seen by the maintainer) is an integration branch for | |
| things that are not quite ready for inclusion yet (see "Integration | |
| Branches" below). | |
| Each of the four branches is usually a direct descendant of the one | |
| above it. | |
| Conceptually, the feature enters at an unstable branch (usually 'next' | |
| or 'seen'), and "graduates" to 'master' for the next release once it is | |
| considered stable enough. | |
| Merging upwards | |
| ~~~~~~~~~~~~~~~ | |
| The "downwards graduation" discussed above cannot be done by actually | |
| merging downwards, however, since that would merge 'all' changes on | |
| the unstable branch into the stable one. Hence the following: | |
| .Merge upwards | |
| [caption="Rule: "] | |
| ===================================== | |
| Always commit your fixes to the oldest supported branch that requires | |
| them. Then (periodically) merge the integration branches upwards into each | |
| other. | |
| ===================================== | |
| This gives a very controlled flow of fixes. If you notice that you | |
| have applied a fix to e.g. 'master' that is also required in 'maint', | |
| you will need to cherry-pick it (using linkgit:git-cherry-pick[1]) | |
| downwards. This will happen a few times and is nothing to worry about | |
| unless you do it very frequently. | |
| Topic branches | |
| ~~~~~~~~~~~~~~ | |
| Any nontrivial feature will require several patches to implement, and | |
| may get extra bugfixes or improvements during its lifetime. | |
| Committing everything directly on the integration branches leads to many | |
| problems: Bad commits cannot be undone, so they must be reverted one | |
| by one, which creates confusing histories and further error potential | |
| when you forget to revert part of a group of changes. Working in | |
| parallel mixes up the changes, creating further confusion. | |
| Use of "topic branches" solves these problems. The name is pretty | |
| self explanatory, with a caveat that comes from the "merge upwards" | |
| rule above: | |
| .Topic branches | |
| [caption="Rule: "] | |
| ===================================== | |
| Make a side branch for every topic (feature, bugfix, ...). Fork it off | |
| at the oldest integration branch that you will eventually want to merge it | |
| into. | |
| ===================================== | |
| Many things can then be done very naturally: | |
| * To get the feature/bugfix into an integration branch, simply merge | |
| it. If the topic has evolved further in the meantime, merge again. | |
| (Note that you do not necessarily have to merge it to the oldest | |
| integration branch first. For example, you can first merge a bugfix | |
| to 'next', give it some testing time, and merge to 'maint' when you | |
| know it is stable.) | |
| * If you find you need new features from the branch 'other' to continue | |
| working on your topic, merge 'other' to 'topic'. (However, do not | |
| do this "just habitually", see below.) | |
| * If you find you forked off the wrong branch and want to move it | |
| "back in time", use linkgit:git-rebase[1]. | |
| Note that the last point clashes with the other two: a topic that has | |
| been merged elsewhere should not be rebased. See the section on | |
| RECOVERING FROM UPSTREAM REBASE in linkgit:git-rebase[1]. | |
| We should point out that "habitually" (regularly for no real reason) | |
| merging an integration branch into your topics -- and by extension, | |
| merging anything upstream into anything downstream on a regular basis | |
| -- is frowned upon: | |
| .Merge to downstream only at well-defined points | |
| [caption="Rule: "] | |
| ===================================== | |
| Do not merge to downstream except with a good reason: upstream API | |
| changes affect your branch; your branch no longer merges to upstream | |
| cleanly; etc. | |
| ===================================== | |
| Otherwise, the topic that was merged to suddenly contains more than a | |
| single (well-separated) change. The many resulting small merges will | |
| greatly clutter up history. Anyone who later investigates the history | |
| of a file will have to find out whether that merge affected the topic | |
| in development. An upstream might even inadvertently be merged into a | |
| "more stable" branch. And so on. | |
| Throw-away integration | |
| ~~~~~~~~~~~~~~~~~~~~~~ | |
| If you followed the last paragraph, you will now have many small topic | |
| branches, and occasionally wonder how they interact. Perhaps the | |
| result of merging them does not even work? But on the other hand, we | |
| want to avoid merging them anywhere "stable" because such merges | |
| cannot easily be undone. | |
| The solution, of course, is to make a merge that we can undo: merge | |
| into a throw-away branch. | |
| .Throw-away integration branches | |
| [caption="Rule: "] | |
| ===================================== | |
| To test the interaction of several topics, merge them into a | |
| throw-away branch. You must never base any work on such a branch! | |
| ===================================== | |
| If you make it (very) clear that this branch is going to be deleted | |
| right after the testing, you can even publish this branch, for example | |
| to give the testers a chance to work with it, or other developers a | |
| chance to see if their in-progress work will be compatible. `git.git` | |
| has such an official throw-away integration branch called 'seen'. | |
| Branch management for a release | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| Assuming you are using the merge approach discussed above, when you | |
| are releasing your project you will need to do some additional branch | |
| management work. | |
| A feature release is created from the 'master' branch, since 'master' | |
| tracks the commits that should go into the next feature release. | |
| The 'master' branch is supposed to be a superset of 'maint'. If this | |
| condition does not hold, then 'maint' contains some commits that | |
| are not included on 'master'. The fixes represented by those commits | |
| will therefore not be included in your feature release. | |
| To verify that 'master' is indeed a superset of 'maint', use git log: | |
| .Verify 'master' is a superset of 'maint' | |
| [caption="Recipe: "] | |
| ===================================== | |
| `git log master..maint` | |
| ===================================== | |
| This command should not list any commits. Otherwise, check out | |
| 'master' and merge 'maint' into it. | |
| Now you can proceed with the creation of the feature release. Apply a | |
| tag to the tip of 'master' indicating the release version: | |
| .Release tagging | |
| [caption="Recipe: "] | |
| ===================================== | |
| `git tag -s -m "Git X.Y.Z" vX.Y.Z master` | |
| ===================================== | |
| You need to push the new tag to a public Git server (see | |
| "DISTRIBUTED WORKFLOWS" below). This makes the tag available to | |
| others tracking your project. The push could also trigger a | |
| post-update hook to perform release-related items such as building | |
| release tarballs and preformatted documentation pages. | |
| Similarly, for a maintenance release, 'maint' is tracking the commits | |
| to be released. Therefore, in the steps above simply tag and push | |
| 'maint' rather than 'master'. | |
| Maintenance branch management after a feature release | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| After a feature release, you need to manage your maintenance branches. | |
| First, if you wish to continue to release maintenance fixes for the | |
| feature release made before the recent one, then you must create | |
| another branch to track commits for that previous release. | |
| To do this, the current maintenance branch is copied to another branch | |
| named with the previous release version number (e.g. maint-X.Y.(Z-1) | |
| where X.Y.Z is the current release). | |
| .Copy maint | |
| [caption="Recipe: "] | |
| ===================================== | |
| `git branch maint-X.Y.(Z-1) maint` | |
| ===================================== | |
| The 'maint' branch should now be fast-forwarded to the newly released | |
| code so that maintenance fixes can be tracked for the current release: | |
| .Update maint to new release | |
| [caption="Recipe: "] | |
| ===================================== | |
| * `git checkout maint` | |
| * `git merge --ff-only master` | |
| ===================================== | |
| If the merge fails because it is not a fast-forward, then it is | |
| possible some fixes on 'maint' were missed in the feature release. | |
| This will not happen if the content of the branches was verified as | |
| described in the previous section. | |
| Branch management for next and seen after a feature release | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| After a feature release, the integration branch 'next' may optionally be | |
| rewound and rebuilt from the tip of 'master' using the surviving | |
| topics on 'next': | |
| .Rewind and rebuild next | |
| [caption="Recipe: "] | |
| ===================================== | |
| * `git switch -C next master` | |
| * `git merge ai/topic_in_next1` | |
| * `git merge ai/topic_in_next2` | |
| * ... | |
| ===================================== | |
| The advantage of doing this is that the history of 'next' will be | |
| clean. For example, some topics merged into 'next' may have initially | |
| looked promising, but were later found to be undesirable or premature. | |
| In such a case, the topic is reverted out of 'next' but the fact | |
| remains in the history that it was once merged and reverted. By | |
| recreating 'next', you give another incarnation of such topics a clean | |
| slate to retry, and a feature release is a good point in history to do | |
| so. | |
| If you do this, then you should make a public announcement indicating | |
| that 'next' was rewound and rebuilt. | |
| The same rewind and rebuild process may be followed for 'seen'. A public | |
| announcement is not necessary since 'seen' is a throw-away branch, as | |
| described above. | |
| DISTRIBUTED WORKFLOWS | |
| --------------------- | |
| After the last section, you should know how to manage topics. In | |
| general, you will not be the only person working on the project, so | |
| you will have to share your work. | |
| Roughly speaking, there are two important workflows: merge and patch. | |
| The important difference is that the merge workflow can propagate full | |
| history, including merges, while patches cannot. Both workflows can | |
| be used in parallel: in `git.git`, only subsystem maintainers use | |
| the merge workflow, while everyone else sends patches. | |
| Note that the maintainer(s) may impose restrictions, such as | |
| "Signed-off-by" requirements, that all commits/patches submitted for | |
| inclusion must adhere to. Consult your project's documentation for | |
| more information. | |
| Merge workflow | |
| ~~~~~~~~~~~~~~ | |
| The merge workflow works by copying branches between upstream and | |
| downstream. Upstream can merge contributions into the official | |
| history; downstream base their work on the official history. | |
| There are three main tools that can be used for this: | |
| * linkgit:git-push[1] copies your branches to a remote repository, | |
| usually to one that can be read by all involved parties; | |
| * linkgit:git-fetch[1] that copies remote branches to your repository; | |
| and | |
| * linkgit:git-pull[1] that does fetch and merge in one go. | |
| Note the last point. Do 'not' use 'git pull' unless you actually want | |
| to merge the remote branch. | |
| Getting changes out is easy: | |
| .Push/pull: Publishing branches/topics | |
| [caption="Recipe: "] | |
| ===================================== | |
| `git push <remote> <branch>` and tell everyone where they can fetch | |
| from. | |
| ===================================== | |
| You will still have to tell people by other means, such as mail. (Git | |
| provides the linkgit:git-request-pull[1] to send preformatted pull | |
| requests to upstream maintainers to simplify this task.) | |
| If you just want to get the newest copies of the integration branches, | |
| staying up to date is easy too: | |
| .Push/pull: Staying up to date | |
| [caption="Recipe: "] | |
| ===================================== | |
| Use `git fetch <remote>` or `git remote update` to stay up to date. | |
| ===================================== | |
| Then simply fork your topic branches from the stable remotes as | |
| explained earlier. | |
| If you are a maintainer and would like to merge other people's topic | |
| branches to the integration branches, they will typically send a | |
| request to do so by mail. Such a request looks like | |
| ------------------------------------- | |
| Please pull from | |
| <URL> <branch> | |
| ------------------------------------- | |
| In that case, 'git pull' can do the fetch and merge in one go, as | |
| follows. | |
| .Push/pull: Merging remote topics | |
| [caption="Recipe: "] | |
| ===================================== | |
| `git pull <URL> <branch>` | |
| ===================================== | |
| Occasionally, the maintainer may get merge conflicts when they try to | |
| pull changes from downstream. In this case, they can ask downstream to | |
| do the merge and resolve the conflicts themselves (perhaps they will | |
| know better how to resolve them). It is one of the rare cases where | |
| downstream 'should' merge from upstream. | |
| Patch workflow | |
| ~~~~~~~~~~~~~~ | |
| If you are a contributor that sends changes upstream in the form of | |
| emails, you should use topic branches as usual (see above). Then use | |
| linkgit:git-format-patch[1] to generate the corresponding emails | |
| (highly recommended over manually formatting them because it makes the | |
| maintainer's life easier). | |
| .format-patch/am: Publishing branches/topics | |
| [caption="Recipe: "] | |
| ===================================== | |
| * `git format-patch -M upstream..topic` to turn them into preformatted | |
| patch files | |
| * `git send-email --to=<recipient> <patches>` | |
| ===================================== | |
| See the linkgit:git-format-patch[1] and linkgit:git-send-email[1] | |
| manpages for further usage notes. | |
| If the maintainer tells you that your patch no longer applies to the | |
| current upstream, you will have to rebase your topic (you cannot use a | |
| merge because you cannot format-patch merges): | |
| .format-patch/am: Keeping topics up to date | |
| [caption="Recipe: "] | |
| ===================================== | |
| `git pull --rebase <URL> <branch>` | |
| ===================================== | |
| You can then fix the conflicts during the rebase. Presumably you have | |
| not published your topic other than by mail, so rebasing it is not a | |
| problem. | |
| If you receive such a patch series (as maintainer, or perhaps as a | |
| reader of the mailing list it was sent to), save the mails to files, | |
| create a new topic branch and use 'git am' to import the commits: | |
| .format-patch/am: Importing patches | |
| [caption="Recipe: "] | |
| ===================================== | |
| `git am < patch` | |
| ===================================== | |
| One feature worth pointing out is the three-way merge, which can help | |
| if you get conflicts: `git am -3` will use index information contained | |
| in patches to figure out the merge base. See linkgit:git-am[1] for | |
| other options. | |
| SEE ALSO | |
| -------- | |
| linkgit:gittutorial[7], | |
| linkgit:git-push[1], | |
| linkgit:git-pull[1], | |
| linkgit:git-merge[1], | |
| linkgit:git-rebase[1], | |
| linkgit:git-format-patch[1], | |
| linkgit:git-send-email[1], | |
| linkgit:git-am[1] | |
| GIT | |
| --- | |
| Part of the linkgit:git[1] suite |