Chapter 19

Performing A Release

For each project or product, there is time where a release needs to be created. This process differs from one company or organization to another.

Git does not specify when it comes to the release process. With tags and branches, however, Git provides powerful tools that support a very wide range of release processes.

This workflow describes an example of a release process for a typical web project. In our web project, there are always a productive release and a future release. In a productive release major bugs and security risks are resolved very quickly (in the so-called hotfixes). This new release is run through a detailed multi-day test period (code freeze phase) before being published. At the same time, development for the next release can proceed.

This workflow shows how a release process can be implemented for a project with Git, such that

  • Hotfixes are supported on the productive release,
  • Parallel work on a new release during the code freeze phase is possible
  • It is guaranteed that all errors that were fixed as hotfixes or during the test phase, flow back to development,
  • The history of releases and hotfixes is easy to access, and
  • Comparisons between releases and development versions can be done easily

Overview

Figure 19.1 shows the branches required for the development and release process.

The development takes place on the master branch. It does not matter whether or not feature branches are used. It is only important that the master branch contains the code that should lead to the next release.

During the release preparation, a separate codefreeze branch is used to stabilize the future release. At the same time, development on the master branch for the next release can proceed.

Once the stabilization is completed, a release commit is created on the stable branch and simultaneously a release tag is generated.

If a fatal error occurs in the productive release, a new hot fix branch will be created. After troubleshooting, a hotfix commit is performed on the stable branch and a release tag is created.

The codefreeze branch and the hotfix branch exist only so long as the stabilizing or troubleshooting takes place.

The changes during the stabilization and the hotfix will always be returned through merges with the master branch.

Requirements

Only one productive release: There is only one productive release, i.e., there are not multiple versions of the product or project maintained. Git can handle multiple versions but this workflow is designed to deal with one productive release.

Stable development: The development branch is well tested and the expected errors in the code freeze phase are manageable so that this can be completed in a few days.

Full release: New things and changes on the development branch always go into the next release.

Workflow “Performing A Release”

A release is created for a project. The preparation for the release takes place in a separate branch. Fixes can be done on the productive release.

Figure 19.1: Workflow overview

Process and Implementation

Preparation: Creating a stable branch

The following section describes the unique preparation of the repository to perform a release.

This workflow requires a branch named stable. This branch should contain only commits that represent a new release or a hotfix release. The first-parent history of the stable branch can be used as the release history, which can be displayed using the log command.

> git checkout stable 

> git log --first-parent –oneline 

5901ec9 Hotfix-Release-2.0.1 
b955c9c Release-2.0.0 
5d0173d Release-1.0.0 
3a05e26 init 

The following are the parameters used in the command.

--first-parent: Only the first parent is considered.

--oneline: Only one line of the log output is printed.

Figure 19.2: Starting the first release

It is important to define the beginning of the stable branch correctly. If the stable branch will be created at the first release commit, then the previous commits of the master branch must be included in the first-parent history (See Figure 19.2).

Figure 19.3: Starting the stable branch with the first commit

It is better to start the stable branch at the first commit of the master branch. This way, only one unnecessary commit will be included in the release history (see the first commit in Figure 19.3).

Step 1: Determine the first commit

Unfortunately, there is no Git command that can be used to find the first commit of a branch. The best way is to display the log and look for the last entry.

> git log --oneline --first-parent | tail -1 

3a05e26 init 

The parameters used in the command are as follows.

--oneline: Only prints one line of the output.

--first-parent: Returns only the first parent of each commit. This leads to using fewer resources and thus a faster result.

| tail -1: Prints only the last line of the log output.

Step 2: Creating a stable branch

After the first commit is found, the stable branch can be created. With the branch command, additional branch names can also be specified.

> git branch stable 3a05e26 

Prepare and Create A Release

The following section describes the steps needed to release a project with Git.

Project development takes place on the master branch. On this branch, the necessary unit tests and integration tests are also performed.

When the development is complete and the project is ready to be released, normally more and more intensive tests need to be performed. This phase is commonly referred to as “code freeze.” This means that only code for release-critical bug fixes and their possible workarounds will be implemented. How long this phase lasts depends largely on the development process. This can range from the existing code quality and the tests. It can take a few hours or several weeks.

This should not stop the development for the next release during the code freeze phase, as the stabilization of the release is performed in a separate codefreeze branch. This branch exists only until the new release has been stabilized. The next time you create a release, a new codefreeze branch will be created.

Step 1: Create a codefreeze branch

The codefreeze branch is created based on the current master branch. The checkout command can be used to create the new branch and activate it.

> git checkout -b codefreeze master 

Step 2: stabilize with the codefreeze branch

In the codefreeze branch, only errors that are preventing a release will be corrected. The fix is carried out according to the principle of minimal change. If there is no simple solution to the minimal error, a workaround is implemented if necessary.

The new commits on the codefreeze branch must be regularly merged to the master branch. These one-off fixes will also be eliminated from the current development.

> git checkout master

> git merge codefreeze

Workarounds should be incorporated in the codefreeze branch, as these will be retained in the master branch. In the master branch workarounds can be reverted (for example, using the revert command) and a better implementation created (see Figure 19.4).

Figure 19.4: Dealing with bug fixes and workarounds

Step 3: Create a release

After the codefreeze branch has been successfully tested, the release can be created.

As such, a merge from the codefreeze branch must be carried out on the stable branch. It is important that in the stable branch there are no commits that have not been tested on the codefreeze branch. Such commits would lead to a merge such that there is a major release in the stable branch that has not been tested in this compilation.

The following log command checks if there are commits in the stable branch that are missing in the codefreeze branch. No output means there are no new commits in the stable branch.

> git log codefreeze..stable --oneline

If the log command returns an output, a renewed merge from the stable branch to the codefreeze branch and the tests necessary for the release must be done again.

If the log output is empty, the merge of the codefreeze branch can be performed in the stable branch.

Normally, Git would do a fast-forward merge in this merge, because we have ensured that there are no new commits in the stable branch. However, to obtain a meaningful first-parent history on the stable branch, use the --no-ff option. You should also use a comment that clearly identifies the new commits for the release.

> git checkout stable

> git merge codefreeze --no-ff -m "Release-2.0.0" 

The --no-ff option indicates that the merge command should not perform a fast-forward merge, i.e., it will always create a new commit.

In addition to the commit, a new tag for the release should be created. The tag can be used to quickly access the release commit, e.g. to be used by the diff command.

> git tag -a release-2.0.0 -m "Release-2.0.0"

Finally, the codefreeze branch will be deleted as this branch is only used to stabilize and will be recreated in the next release.

> git branch -d codefreeze 

Step 4: Update the master branch

Now that the release was performed to guarantee that any changes in the release are also included in the master branch.

Figure 19.5: Performing a release

Although all bug fix commits in the codefreeze branch are already merged into the master branch, the new release commit still exists (see Figure 19.5). Although this release commit does not change any files and is therefore irrelevant to the master branch, queries such as “Which commit is in the stable branch, but not in the master branch?” would show regularly. Therefore, the stable branch needs to be merged with the master branch.

> git checkout master 

> git merge stable -m "Nach Release-2.0.0" 

Thus, from the perspective of version management, the new release has been completely created.

Creating A Hotfix

A hotfix is an urgent change that is supposed to be as fast as possible and independent from other changes. A hotfix is implemented directly against the version of the current release. Less important errors in a web application will typically be rectified in the next release. However, a mistake that makes it impossible to work with the system or that can lead to security risks, must be corrected immediately.

Step 1: Create a hotfix branch and troubleshoot

The error correction takes place on a separate hotfix branch. In order to enable parallel processing of multiple hotfixes, everyone gets their own branch.

The starting point is the stable branch, which points to the last productive release.

> git checkout -b hotfix-a1 stable 

Now the necessary changes for the project can be made.

Step 2: Verify that parallel hotfixes have taken place

If the error is corrected and a new release should be created, you must check the commit history to see if there was another hotfix in the meantime. To do this, use the log command to find commits that are in the stable branch, but not in the hotfix branch.

> git log hotfix-a1..stable --oneline

If in the meantime there were other changes in the stable branch, before the hotfix can be installed, you have to check if the other changes will work with the hotfix. So that the history will remain linear, the hotfix should be placed as the last commit of the stable branches by rebasing (see Figure 19.6).

Figure 19.6: Rebasing the hotfix branch

> git rebase stable

Now the hotfix commits are based on the last commit of the stable branch.

Step 3: Release the hotfix

In order to officially release the hotfix, the hotfix branch has to be merged with the stable branch. Again a fast-forward merge is not allowed in order to create a new commit. The merge comment should be used to specify the necessary release information.

> git checkout stable

> git merge hotfix-a1 --no-ff -m "Hotfix-Release-2.0.1"

In addition to the commit, a new tag will be created for the release.

> git tag -a release-2.0.1 -m "Hotfix-Release 2.0.1" 

Finally, you can delete the hotfix branch.

Step 4: Accept hotfix changes in another branch

Errors that were fixed with a hotfix branch must be transferred to the other active branch.

Figure 19.7: Accepting hotfixes in the codefreeze and master branches

During a code freeze phase, the hotfix must be brought to the codefreeze branch only. Then, the changes in the codefreeze branch are transferred to the master branch (see Figure 19.7).

> git checkout codefreeze 

> git merge stable -m "Hotfix 2.0.1" 

> git checkout master 

> git merge codefreeze -m "Hotfix 2.0.1"

Figure 19.8: Accepting hotfixes in the master branch

During a non-code freeze phase, the changes are transferred directly to the master branch (see Figure 19.8).

> git checkout master 

> git merge stable -m "Hotfix 2.0.1"

Why Not the Alternatives?

Why Not with Tags Only?

In the workflow described a stable branch and additional tags for identifying the releases are used. Would tags only be insufficient?

For pure marking and thus reproducing the releases, the use of rich tags would actually be sufficient.

However, when it comes to understanding the history of releases and hotfix releases, then tags alone are impractical. You could only guess based on the tag name in chronological order. With a stable branch, you can use the first-parent history.

Why Not Do without Tags?

Tags are symbolic names for commits. If you want to compare the current development version with a particular release (using the diff command), then tags are more practical than commit hashes.

> git diff release-1.0.0 

If you were to eliminate the tags, you would first have to search for the right commit in the stable branch and then specify the hash.

> git diff 5d0173d

Why No Fast-Forward Merges?

In Git, branches are only references to commits. If a branch is activated (using the checkout command), then the reference to each new commit is automatically updated. There is no historical information on which commit was created on which branch. The only “heuristic” option is to use the first-parent history of a branch.

A fast-forward merge results in two branches pointing to the same commit. If the first-parent history is used, it is no longer traceable in which of the two branches the previous commit was created.

If you do not allow fast-forward merges, a new commit is always created. The first parent points to the last commit in the current branch and the second parent to the added commit.

Why Not Implement A Hotfix Directly on the stable Branch?

The workflow describes that for correcting a serious error, a separate hotfix branch should be created. In principle, it would also be possible to work directly on the stable branch.

However, under certain circumstances, commits with no associated releases would appear in the first-parent history of the stable branch. This happens when more than one commit must be created for a hotfix.

Also, the parallel creation of hotfixes can be difficult.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.219.130