Chapter 15

Developing on the Same Branch

In a centralized version control, such as Subversion, the team often works on a common branch. All developers copy this branch to their local workspace. There, changes take place, which are then written back to the version control system.

A very similar workflow can also be enacted with Git. This similarity facilitates transition and makes its use uncomplicated and fast.

Every developer creates a clone of the central repository and works on his or her copy of the master branch.

Once the development results are ready to be made available to others, the local master branch is merged with the central master branch. This results in merge commits, and at the same time changes are being made by other developers. The merge is done in the local repository, and the combined supernatant is then transferred to the central repository.

The advantage of this workflow is the rapid detection of conflicts, as changes from a developer are frequently pooled together with changes from other developers.

On the other hand, this workflow will create many merge commits, and as such clutter the commit history. It will no longer be possible to use the first-parent history used in the workflow “Working with feature branches.”

The workflow in this chapter describes

  • how local development on the master branch works,
  • how one’s own results are published in the central repository, and
  • how the results may be used by other developers.

Overview

Figure 15-1 shows a typical scenario for this workflow. At the top is the central repository. At the bottom are Developer A’s repository and Developer B’s repository.

Every developer starts with his or her local master branch, producing small incremental commits necessary to return to a previous state and to document his or her steps.

Once a task is completed or if another developer needs the intermediate level, the commits are transmitted to the central repository with the push command. As long as the central master branch has not changed in the meantime, the push command will be successful.

However, often there will be commits from another developer on the central master branch. As such, the pull command must be used to merge the changes in the local repository with the changes from the central repository. This creates a merge commit in the local repository, which is then transmitted to the central repository with the push command. This is shown in Figure 15-1 as the last merge commit. Developer A had already transferred his commit, and Developer B had merges her commit with the existing commit.

A developer can also use the pull command to bring the changes from other developers into his or her own repository.

Requirements

  • The commit history does not have to be “nice”: The commit history is only needed as a safety net against data loss and for comparison with the older versions. The workflow "Developing with feature branches” is another possible application of the commit history.
  • Continuous integration for the central master branch: This workflow will create a lot of merge commits, so there is always a risk that there will be problems with the merged version. Therefore, it is important to continuously build the master branch on the central repository and perform testing so that the developers will learn of any problems that arise immediately.

Workflow: Developing on the Same Branch

All developers work on the same branch in their local repository and merge the results into the main branch on the central repository.

Figure 15.1: Workflow overview

Process and Implementation

For the following processes, we start from the central repository and a local clone of development.

Working on the master Branch

Step 1: Update the master branch

Before starting a new task, it is always advisable that you get the latest from the central repository. This way, the risk of file conflicts will be minimized.

If you want to make sure that there are no local commits that have not been transferred to the central repository, you should use the --ff-only parameter. This parameter prevents Git from automatically performing a merge with the central changes.

> git pull --ff-only 

The --ff-only parameter prevents merge commits by allowing only fast-forward merges in the pull command.

Step 2: Make local changes

After pulling the current version of the master repository, development on the local machine can be carried out.

This will typically create incremental commits in Git, which include exactly a subtask, a unit of refactoring, or a fix. This way, the developers will be able to go back to a previous version or compare files with the current version. Before proceeding to the next step, this step should always be terminated with a commit of the local changes.

> git commit -m "Method X revised" 

Step 3: Merge local changes with central changes

If the development tasks are completed or if another developer demands an intermediate version, the local changes must be transferred to the central repository.

Since this will only work if there were no changes in the central repository at that time, it is always advisable to move forward with the pull command to fetch all the central changes.

> git pull 

 Already up-to-date. 

If there were no changes when the pull command was executed, an “up-to-date” message will be printed.

If there were changes but Git was able to do a merge automatically, no “conflict” message will be displayed and Git will print the names of the files that had been changed.

remote: Counting objects: 5, done. 
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done. 
From projectX 
   2cd173f..e10bb4d   master    -> origin/master 
Merge made by recursive. 
   foo |    1 + 
   1 files changed, 1 insertions(+), 0 deletions(-) 

If there are conflicts between the central and local changes, these will be displayed in the output.

remote: Counting objects: 8, done. 
remote: Compressing objects: 100% (3/3), done.
remote: Total 5 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done. 
From projectX 
   9139636..fa60160 master	    -> origin/master
Auto-merging foo 

CONFLICT (content): Merge conflict in foo Conflict resolution can be done in the normal way. The adjusted files of the previously incomplete merge commit are added using the add command. Subsequently, the conflicted merge needs to be completed using the commit command.

> git add foo 

> git commit 

If you do not provide a description for this commit command, Git will automatically generate a merge description that describes the conflicts that occurred.

Merge branch 'master' of projectX

Conflicts: 
foo

Step 4: Transfer local changes to the central repository

If the previous step was successfully completed, there will be a consolidated project status in the local repository.

Before this version is transferred to the central repository, run the local tests to uncover any problems.

If you are satisfied with the quality of the version, you can transfer the local changes to the control center with the push command.

> git push 

If the push command is terminated without an error message, that means the commits successfully arrived in the central repository.

If in the meantime another developer had done a commit, the push command will end with an error message:

To projectX.git 
 ! [rejected]    master -> master (non-fast-forward) 
error: failed to push some refs to '/Users/rene/temp/project.git/' 
To prevent you from losing history, non-fast-forward updates were 
rejected. Merge the remote changes (e.g. 'git pull') before pushing 
again. See the 'Note about fast-forwards' section of 
'git push --help' for details. 

To get the new changes, you need to call the pull command again. Here, another merge commit will be created. In order not to complicate the history with two merge commits, you should delete the first merge commit with the reset command.

> git reset --hard ORIG_HEAD 

The --hard parameter reconstructs both the workspace and the staging area in the specified commit. ORIG_HEAD in the command above is a symbolic name for the commit before the last pull or merge command.

Afterward, go back to Step 3 and bring the changes to the central repository with the pull command.

Why Not the Alternatives?

Why not rebase instead of merge?

The workflow described generates many merge commits, making the commit history difficult to read.

An alternative would be to merge the local changes with the central changes with a rebase (using the --rebase parameter with the pull command).

> git pull --rebase

With a rebase your local changes will be run again commit by commit on the central master branch. That is, a rebase will create new commits, but include the same changes.

Figure 15.2: Rebase instead of merge

Figure 15.2 shows the different commit histories that will be generated with a merge and a rebase.

At first glance, it is striking to learn that there is no more branching in the rebase and thus the history is linear. This advantage is offset by the fact that its commits are now in the history, so a developer will never have detailed versions in his or her local environment. That always happens when multiple commits are copied using a rebase. As such, the developer can only review the last commit. In addition, the copied versions are not tested.

As an example, take commit F' in Figure 15.2. It is caused by a rebase of commit G. As long as there are no conflicts when copying the changes to commit F, this will be ignored. However, it is conceivable that there may have been substantive errors that cause this version to not work.

As long as you just want to know who has made what changes in the commits, you should be fine. However, once you try to troubleshoot in the commit history, those commits will start to be annoying.

If you will be working with rebase a lot, you can define the default behavior of the pull command by configuring the following setting:

> git config branch.master.rebase true 

The branch.master.rebase parameter determines what branch rebase should be enabled by default. The branch name (master) can be replaced by any other branch name.

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

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