Chapter 23
Using Other Version Controls in Parallel
In many businesses and organizations, the tool for the versioning and the related processes is managed centrally. Individual projects and teams cannot just use a different version control system such as Git. The enterprise-wide migration to Git requires feasibility studies, strategic decisions, migration plans, etc. --so much time.
Despite everything, it is possible to use some skills of Git in the local development environment and synchronize the results with the central versioning.
For a local use Git provides the following advantages:
This workflow shows how a local Git repository can work together with a central versioning so that
For interconnectivity with Subversion, there is the git-svn command so this workflow is not required.
Overview
To describe the collaboration of Git and a central versioning, we use CVS. The basic sequence works the same for other central version controls.
Figure 23.1 shows a CVS server and repositories on the developer computer.
The developer has two local Git repositories. A “sync repository,” which is used to synchronize with the central version, and a “work repository,” in which the actual development takes place.
The sync repository is connected to the central version control (CVS-directories) and includes Git objects (in the .git directory). The central versioning is configured (through the .cvsignore file) such that Git objects are ignored. Git is configured (through the .gitignore file) so that CVS metadata is ignored.
First, files that have changed in the central version control are recorded in the sync repository (cvs update). Then a new Git commit is created on the cvs branch. This is then imported to the work repository (fetch command) and then merged with the master branch using the merge command.
In order to apply changes local to the master branch to the central versioning, the new commits on the master branch are transferred to the sync repository (with the push command). In the sync repository, the master branch is merged with the cvs branch. After that, the changes are saved in the central version control (with cvs commit).
Requirements
Optimistic locking: The central version management must support optimistic locking, i.e., files can be changed without acquiring locks.
Ignoring files and directories: The central versioning can exclude files and directories.
Flexibility of the project directory: The development tools (e.g. the build tools) do not require that the project be stored in exactly one place in the file system.
Workflow “Working with Other Version Controls in Parallel”
The company or team uses a centralized version control system. Individual developers are working with Git and synchronizing changes with the central system.
Figure 23.1: Workflow overview
Process and Implementation
You need the following information from your central versioning:
Initial Setup of the Repository
The following steps show how the sync repository and the work repository are set up initially. The starting point is an existing local CVS project (cvsproject), which was created with cvs checkout.
Step 1: Create new sync repository
First, a new Git repository is initialized in the CVS project directory.
> cd cvsproject
> git init
Step 2: Configure the .gitignore file
All files, except the CVS metafiles, should be imported to the sync repository. Therefore, the CVS directory has to be listed in the .gitignore file.
> echo CVS/ > .gitignore
The echo command creates a new .gitignore file containing the content of CVS/.
Step 3: Configure the .cvsignore file
Git’s meta information is not versioned in the central versioning. So you have to exclude the .git directory and the .gitignore file. In CVS this works by adding the directory and file to the .cvsignore file.
> echo .git >> .cvsignore
> echo .gitignore >> .cvsignore
If the .cvsignore file previously does not exist, it will be created automatically and must be added to the CVS repository with cvs add.
> cvs add .cvsignore
Then, you send the changes to CVS-Server with cvs commit.
> cvs commit
Step 4: Add files to sync repository
Now that all preparation has been completed, the project files can be added to the sync repository.
> git add .
Attention! Version control systems, including Git, have the habit of adapting the end of line characters in text files (LF or CRLF). If the central version control and Git handle line endings differently, you can disable changing line endings in Git: git config core.autocrlf false.
Some central version control systems, including Subversion, utilize a global revision number. In this case, it helps to include this revision number in the Git commit comment. This revision number can be tracked very easily and can reveal which progress had been imported. Unfortunately, CVS does not have such a revision number.
> git commit -m "Initial import of CVS"
Step 5: Create a cvs branch in the sync repository
The sync repository will work in the future on a separate cvs branch. This branch has yet to be created and activated.
> git checkout -b cvs
Step 6: Create a work repository
The work repository is created as a clone of the sync repository. When you create the clone, the master branch is set as the active branch automatically.
> cd ..
> git clone cvsproject gitproject
With this step, the initial preparation is complete.
Bringing Changes from the Central Version Control
This section describes how innovations from the centralized version control are brought from the sync repository to the work repository.
Step 1: Transfer the modified files into thesync repository
The workspace of the sync repository contains the necessary meta-information for comparison with the central versioning. Therefore, you can obtain changes from the CVS server through this workspace.
> cd cvsproject
> cvs update
Here, the cvs update command can never cause CVS conflicts. In the cvs branch of the sync repository there is always a “clean” old version of the central versioning
Subsequently, changes that have been made through CVS in the sync workspace are compiled using the add command to a Git commit. Then the commit is finished.
> git add --all .
The --all parameter adds new and edited files to the commit and simultaneously removes the deleted files.
> git commit -m "Changes from CVS"
Step 2: Commit changes to the work repository
So far, the commit with the CVS changes only exists in the sync repository. Since the work repository is a clone of the sync repository, the remote entry (origin) is automatically there too. With the fetch command, you can import the new commit with CVS changes to the work repository.
> cd gitproject
> git fetch origin
Step 3: Apply changes to the master branch
At this stage, the changes are only available on the cvs branch and not on the master branch. The final step consists of a merge command. Therefore, this can lead to conflicts if there were parallel changes to the same files in CVS and the local Git. The normal Git tools can be used to clean up the conflicts (see Figure 23.2).
> git merge origin/cvs
After these steps, the current version from the central versioning, which has been merged with the local changes, can be found in the work repository.
Figure 23.2: Copying CVS updates to the master branch
Transferring Changes to the Central Version Control
This section explains how to transfer changes from the work repository to the central version management via the sync repository.
Step 1: Get the latest version from the centralized version control
Before the local changes are transferred to the central version management, the latest changes should always be taken out of the center. To do this, follow the steps from the previous section.
By upgrading, the probability of conflicts is minimized during the subsequent transfer of your own changes to the central versioning. In addition, you can test again if the changes you have made will work with the latest central version.
The local changes on the master branch must be transferred to the sync repository. Since the sync repository was registered with the remote cloning as “origin”, a simple push command will do.
> cd gitproject
> git push
Step 3: Accept changes on the cvs branch
The new commits and updated files are located in the sync repository in the master branch. To apply these changes to the central version control, a merge to the cvs branch is still necessary. This will not cause any conflicts since the cvs branch has no changes (see Figure 23.3).
> cd cvsproject
> git merge --no-commit --no-ff master
The parameters used in the merge command are as follows.
--no-commit: Since there can still be conflicts in the subsequent CVS commit, the Git merge is first performed without a final commit.
--no-ff: This option prevents Git fast-forward merges.
Figure 23.3: Preparing the CVS commit in the cvs branch
Step 4: Transferring changes to the central version control
The local changes can now be transferred to the central version management. Depending on whether there are new files, deleted files or changed files, the necessary commands are run on the central version control, e.g. cvs commit if there were only changed files:
> cvs commit
If there is a conflict during the cvs commit, then there must have been changes since the last cvs update changes that compete with the local changes. In this case, you have to reset the current merge attempt—the open commit.
> git reset --hard HEAD
Then, you can start again at Step 1 to fetch the last competing changes from the central version control and merge them with the master branch.
When you have successfully transferred the changes to the central version control, proceed to the next step.
Step 5: Get updates from the central version control
Some version control systems change files when doing a commit or at the first update after a commit. So you can, for example, get CVS to use the current version number or the history of changes in the head of a file (keyword substitution). Therefore, again it is important to fetch the files from the centralized version control after a successful CVS commit.
> cvs update
Step 6: Perform a commit to the cvs branch
Now it is time to close the open merge commit. Before you do that, add any possible CVS substitutions to the merge commit with the add command:
> git add .
> git commit -m "Changes from Git recorded"
Step 7: Update the master branch in the work repository
After the previous step there is now a new commit on the cvs branch in the sync repository. Before further work, the cvs branch must be with the master branch in the work repository. To this end, the commit is transferred to the work repository first.
> cd gitproject
> git fetch origin
Next, do a merge. This merge is always a fast-forward merge, as there should be no interim changes on the master branch.
> git merge origin/cvs
After these steps, any local changes in the central version control are included. In the work repository there is a version that corresponds to the current version of the central versioning. Figure 23.4 shows all the commits and branches as they are created by the procedure described.
Figure 23.4: Commits and branches after the transfer
Why Not the Alternatives?
Why Not Just One Repository?
The sequence in this workflow also works with just one Git repository, i.e., you can have the local development in the sync repository instead. You then switch between the cvs branch and the master branch, depending on whether you are synchronizing or developing. However, experience has shown that it is difficult to keep track of where and what actions need to be performed.
It often happens that, especially when you are synchronizing, commands are executed on the wrong branch.
Another problem can arise if the meta-information of the central versioning is accidentally deleted during development, for example if you delete the whole CVS directory when refactoring.
18.220.53.93