NAME

gitworkflows - An overview of recommended workflows with Git

SYNOPSIS

  1. git *

DESCRIPTION

This document attempts to write down and motivate some of the workflowelements used for git.git itself. Many ideas apply in general,though the full workflow is rarely required for smaller projects withfewer people involved.

We formulate a set of rules for quick reference, while the prosetries to motivate each of them. Do not always take them literally;you should value good reasons for your actions higher than manpagessuch as this one.

SEPARATE CHANGES

As a general rule, you should try to split your changes into smalllogical 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 moreuseful for later inspection and analysis, for example withgit-blame[1] and git-bisect[1].

To achieve this, try to split your work into small steps from the verybeginning. It is always easier to squash a few commits together thanto split one big commit into several. Don’t be afraid of making toosmall or imperfect steps along the way. You can always go back laterand edit the commits with git rebase —interactive before youpublish them. You can use git stash push —keep-index to run thetest suite independent of other uncommitted changes; see the EXAMPLESsection of git-stash[1].

MANAGING BRANCHES

There are two main tools that can be used to include changes from onebranch on another: git-merge[1] andgit-cherry-pick[1].

Merges have many advantages, so we try to solve as many problems aspossible with merges alone. Cherry-picking is still occasionallyuseful; see "Merging upwards" below for an example.

Most importantly, merging works at the branch level, whilecherry-picking works at the commit level. This means that a merge cancarry over the changes from 1, 10, or 1000 commits with equal ease,which in turn means the workflow scales much better to a large numberof contributors (and contributions). Merges are also easier tounderstand because a merge commit is a "promise" that all changes fromall its parents are now included.

There is a tradeoff of course: merges require a more careful branchmanagement. 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 "maintenancerelease", 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 forstability for master.

There is a fourth official branch that is used slightly differently:

  • pu (proposed updates) is an integration branch for things that arenot quite ready for inclusion yet (see "Integration Branches"below).

Each of the four branches is usually a direct descendant of the oneabove it.

Conceptually, the feature enters at an unstable branch (usually next_or _pu), and "graduates" to master for the next release once it isconsidered stable enough.

Merging upwards

The "downwards graduation" discussed above cannot be done by actuallymerging downwards, however, since that would merge all changes onthe unstable branch into the stable one. Hence the following:

Rule: Merge upwards

Always commit your fixes to the oldest supported branch that requiresthem. Then (periodically) merge the integration branches upwards into eachother.

This gives a very controlled flow of fixes. If you notice that youhave applied a fix to e.g. master that is also required in maint,you will need to cherry-pick it (using git-cherry-pick[1])downwards. This will happen a few times and is nothing to worry aboutunless you do it very frequently.

Topic branches

Any nontrivial feature will require several patches to implement, andmay get extra bugfixes or improvements during its lifetime.

Committing everything directly on the integration branches leads to manyproblems: Bad commits cannot be undone, so they must be reverted oneby one, which creates confusing histories and further error potentialwhen you forget to revert part of a group of changes. Working inparallel mixes up the changes, creating further confusion.

Use of "topic branches" solves these problems. The name is prettyself explanatory, with a caveat that comes from the "merge upwards"rule above:

Rule: Topic branches

Make a side branch for every topic (feature, bugfix, …​). Fork it offat the oldest integration branch that you will eventually want to merge itinto.

Many things can then be done very naturally:

  • To get the feature/bugfix into an integration branch, simply mergeit. If the topic has evolved further in the meantime, merge again.(Note that you do not necessarily have to merge it to the oldestintegration branch first. For example, you can first merge a bugfixto next, give it some testing time, and merge to maint when youknow it is stable.)

  • If you find you need new features from the branch other to continueworking on your topic, merge other to topic. (However, do notdo this "just habitually", see below.)

  • If you find you forked off the wrong branch and want to move it"back in time", use git-rebase[1].

Note that the last point clashes with the other two: a topic that hasbeen merged elsewhere should not be rebased. See the section onRECOVERING FROM UPSTREAM REBASE in 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:

Rule: Merge to downstream only at well-defined points

Do not merge to downstream except with a good reason: upstream APIchanges affect your branch; your branch no longer merges to upstreamcleanly; etc.

Otherwise, the topic that was merged to suddenly contains more than asingle (well-separated) change. The many resulting small merges willgreatly clutter up history. Anyone who later investigates the historyof a file will have to find out whether that merge affected the topicin 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 topicbranches, and occasionally wonder how they interact. Perhaps theresult of merging them does not even work? But on the other hand, wewant to avoid merging them anywhere "stable" because such mergescannot easily be undone.

The solution, of course, is to make a merge that we can undo: mergeinto a throw-away branch.

Rule: Throw-away integration branches

To test the interaction of several topics, merge them into athrow-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 deletedright after the testing, you can even publish this branch, for exampleto give the testers a chance to work with it, or other developers achance to see if their in-progress work will be compatible. git.githas such an official throw-away integration branch called pu.

Branch management for a release

Assuming you are using the merge approach discussed above, when youare releasing your project you will need to do some additional branchmanagement 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 thiscondition does not hold, then maint contains some commits thatare not included on master. The fixes represented by those commitswill therefore not be included in your feature release.

To verify that master is indeed a superset of maint, use git log:

Recipe: Verify master is a superset of maint

git log master..maint

This command should not list any commits. Otherwise, check outmaster and merge maint into it.

Now you can proceed with the creation of the feature release. Apply atag to the tip of master indicating the release version:

Recipe: Release tagging

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 toothers tracking your project. The push could also trigger apost-update hook to perform release-related items such as buildingrelease tarballs and preformatted documentation pages.

Similarly, for a maintenance release, maint is tracking the commitsto be released. Therefore, in the steps above simply tag and pushmaint 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 thefeature release made before the recent one, then you must createanother branch to track commits for that previous release.

To do this, the current maintenance branch is copied to another branchnamed with the previous release version number (e.g. maint-X.Y.(Z-1)where X.Y.Z is the current release).

Recipe: Copy maint

git branch maint-X.Y.(Z-1) maint

The maint branch should now be fast-forwarded to the newly releasedcode so that maintenance fixes can be tracked for the current release:

Recipe: Update maint to new release

  • git checkout maint

  • git merge —ff-only master

If the merge fails because it is not a fast-forward, then it ispossible some fixes on maint were missed in the feature release.This will not happen if the content of the branches was verified asdescribed in the previous section.

Branch management for next and pu after a feature release

After a feature release, the integration branch next may optionally berewound and rebuilt from the tip of master using the survivingtopics on next:

Recipe: Rewind and rebuild next

  • 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 beclean. For example, some topics merged into next may have initiallylooked promising, but were later found to be undesirable or premature.In such a case, the topic is reverted out of next but the factremains in the history that it was once merged and reverted. Byrecreating next, you give another incarnation of such topics a cleanslate to retry, and a feature release is a good point in history to doso.

If you do this, then you should make a public announcement indicatingthat next was rewound and rebuilt.

The same rewind and rebuild process may be followed for pu. A publicannouncement is not necessary since pu is a throw-away branch, asdescribed above.

DISTRIBUTED WORKFLOWS

After the last section, you should know how to manage topics. Ingeneral, you will not be the only person working on the project, soyou 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 fullhistory, including merges, while patches cannot. Both workflows canbe used in parallel: in git.git, only subsystem maintainers usethe 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 forinclusion must adhere to. Consult your project’s documentation formore information.

Merge workflow

The merge workflow works by copying branches between upstream anddownstream. Upstream can merge contributions into the officialhistory; downstream base their work on the official history.

There are three main tools that can be used for this:

  • git-push[1] copies your branches to a remote repository,usually to one that can be read by all involved parties;

  • git-fetch[1] that copies remote branches to your repository;and

  • git-pull[1] that does fetch and merge in one go.

Note the last point. Do not use git pull unless you actually wantto merge the remote branch.

Getting changes out is easy:

Recipe: Push/pull: Publishing branches/topics

git push <remote> <branch> and tell everyone where they can fetchfrom.

You will still have to tell people by other means, such as mail. (Gitprovides the git-request-pull[1] to send preformatted pullrequests 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:

Recipe: Push/pull: Staying up to date

Use git fetch <remote> or git remote update to stay up to date.

Then simply fork your topic branches from the stable remotes asexplained earlier.

If you are a maintainer and would like to merge other people’s topicbranches to the integration branches, they will typically send arequest to do so by mail. Such a request looks like

  1. Please pull from
  2. <url> <branch>

In that case, git pull can do the fetch and merge in one go, asfollows.

Recipe: Push/pull: Merging remote topics

git pull <url> <branch>

Occasionally, the maintainer may get merge conflicts when they try topull changes from downstream. In this case, they can ask downstream todo the merge and resolve the conflicts themselves (perhaps they willknow better how to resolve them). It is one of the rare cases wheredownstream should merge from upstream.

Patch workflow

If you are a contributor that sends changes upstream in the form ofemails, you should use topic branches as usual (see above). Then usegit-format-patch[1] to generate the corresponding emails(highly recommended over manually formatting them because it makes themaintainer’s life easier).

Recipe: format-patch/am: Publishing branches/topics

  • git format-patch -M upstream..topic to turn them into preformattedpatch files

  • git send-email —to=<recipient> <patches>

See the git-format-patch[1] and git-send-email[1]manpages for further usage notes.

If the maintainer tells you that your patch no longer applies to thecurrent upstream, you will have to rebase your topic (you cannot use amerge because you cannot format-patch merges):

Recipe: format-patch/am: Keeping topics up to date

git pull —rebase <url> <branch>

You can then fix the conflicts during the rebase. Presumably you havenot published your topic other than by mail, so rebasing it is not aproblem.

If you receive such a patch series (as maintainer, or perhaps as areader 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:

Recipe: format-patch/am: Importing patches

git am < patch

One feature worth pointing out is the three-way merge, which can helpif you get conflicts: git am -3 will use index information containedin patches to figure out the merge base. See git-am[1] forother options.

SEE ALSO

gittutorial[7],git-push[1],git-pull[1],git-merge[1],git-rebase[1],git-format-patch[1],git-send-email[1],git-am[1]

GIT

Part of the git[1] suite