A centralized workflow is a good fit for a team that has just switched from SVN to GIT. Just like SVN, centralized workflows use the central repository as the only entry point for project changes. Of course, instead of naming the central branch trunk, the default development branch in Git is called Main and all changes are committed to this branch. This workflow requires no branches other than main.
While switching from one version management system to another may seem like a daunting task, moving to Git doesn’t require any changes to the previous workflow. The way team members work together can still be the same.
However, it is important to note that using Git in your development process automatically gives your development team some advantages over SVN. First, Git enables each team member to keep a complete copy of the project locally. Due to the isolated development environment, make each developer can be independent of all other changes in the whole project to develop their own — that is, they may submit new change in their own local copy, don’t need to listen to change in the upstream, until the developers believe that their own development work is ready.
Second, you can use Git’s robust branch merge model. Unlike SVN, Git’s branching model is designed as a fail-safe mechanism, so developers can take a lot of the mental burden off integrating code and sharing collaborative processes. A centralized workflow is not much different from any other workflow in that it uses a remote server to host a project repository for developers to pull and push. However, compared with other workflows, centralized workflows have no explicit definition of pull request or fork patterns. In general, centralized workflows are better suited to teams that have just moved from SVN to Git or smaller teams.
Way to work
The developer starts by cloning the entire repository locally from the central repository. In a local project, you edit, and then commit the changes, just as you would with SVN; However, these commits are only stored locally at this point — as mentioned earlier, these operations are isolated from the central repository. This allows developers to delay synchronization upstream until they feel they need to.
When publishing their changes to the central repository, the developer executes a push command to push the local main branch to the central repository. This operation is similar to SVN COMMIT, except that push pushes all changes that are not in the remote repository to the remote at once.
Initialize the central repository
Before that happens, someone needs to create a central repository on a remote server. If it is a brand new project, initialize an empty repository. Otherwise, import an existing Git or SVN repository.
The central repository should always be a bare repository (one that does not contain a working directory), which can be created with the following command:
ssh user@host git init --bare /path/to/repo.git
Copy the code
Replace user with a valid SSH username, host with a valid IP or domain name, and /path/to/ rebo.git with your desired remote server path. Note that the.git extension at the end of the path is usually left at the end to indicate that the remote repository is a bare repository.
Hosted central repository
Most of the time, we no longer need to maintain git Server ourselves, but instead use a third-party service to host it and let them create a central repository for us, such as GitLab or Github. In this case, a third-party service handles the process of initializing a bare repository for you. Once created, the hosting service provides the address of a central repository so that it can be used locally.
Clone Central Warehouse
Next, the developer creates a local copy of the entire project. Use git clone to do this:
git clone ssh://user@host/path/to/repo.git
Copy the code
When you clone the repository, Git automatically adds an alias name called Origin to the remote repository, since you’ll be interacting with it in the future.
Edit and commit changes
Once the local copy is cloned, developers can make changes to the repository using the standard Git commit process: edit, staging, commit. In case you’re not familiar with the concept of staging, this is a way to prepare for committing only a portion of your changes without committing all of your local changes. This capability allows developers to maintain a high level of focus on each commit, even if the local repository already contains a large number of changes, and still commit only a small portion of the code.
git status # View the state of the repo
git add <some-file> # Stage a file
git commit # Commit a file</some-file>
Copy the code
Note that since the above commands only create commit records locally, John can repeat these actions over and over again without worrying about the impact on the central repository. This makes a lot of sense when you’re working on a big feature that needs to be broken down into small steps.
Push submissions to the central repository
Once new changes are committed to the local repository, we need to push them to the remote repository in order to share them with other developers.
git push origin main
Copy the code
This command pushes new local submissions to the central repository. When changes are pushed to the central repository, it is possible that some other developer has previously pushed a section of code that conflicts with this update. Git will output some information indicating that a push conflict occurred. In this case, run the git pull command first. We will delve into the conflict scenarios mentioned here in the following paragraphs.
To deal with conflict
The central repository represents the official project code, so the submission history of the central repository should be sacrosanct. If the developer’s local commit history is inconsistent with the central repository’s commit history, Git will refuse to push changes to the central repository because it overwrites the central repository’s commit history.
It is appropriate for developers to update the remote commit history from the central repository before pushing changes, and then rebase the local changes to the top of the remote commit record. It’s like saying: Let my changes build on everyone else’s work. The result of the operation is a perfectly linear commit history.
If a local change conflicts with an upstream commit, Git pauses the rebase process and lets you resolve the conflict manually. You use the same git status and git add commands you use to initiate a commit. This unified behavior makes it easier for novices to deal with conflicts during the merge process. Git also provides a simple command to exit the rebase process, start over, or find someone else to help you if something goes horribly wrong during the merge process.
For example,
Let’s take a concrete example of how a typical small team can collaborate using a centralized workflow. In the example, there are two developers, Li Lei and Han Meimei, who develop their own features independently and then share their work through the central repository.
Li Lei and his function
In his local repository, Li lei developed his own functionality following the standard Git submission process: edit, staging, and commit.
Keeping in mind that these operations are local, Li Lei can do them countless times without worrying about affecting the central warehouse.
Han Meimei and her function
At the same time, Han meimei also developed her own features in her own local environment, again through the process of: Edit, save, submit. Like Li Lei, Han Meimei also need not worry about what his doings can cause to the central warehouse. And she didn’t care what Li Lei was doing, because all the local warehouses were separate.
Li Lei publishes his features
When Li Lei has finished developing the feature, he should publish the local commit to the central repository so that the rest of the team can use the new feature. It can be used like thisgit push
Command:
git push origin main
Copy the code
Remember origin is an alias that Git created automatically to point to the central repository when Li Lei first cloned the contents of the central repository? The main parameter tells Git that this release is pushing changes from the local main branch to the main branch of the central repository. Since there has not been any update of the central warehouse since Li Lei first cloned the content of the central warehouse at this moment, this push operation will not cause any conflict and the release result will come as scheduled.
Han meimei tries to release new features
Let’s see what happens if Han Meimei tries to push her own new feature after Li Lei’s push is complete. First, Han meimei will use the same command for push:
git push origin main
Copy the code
However, since the local commit history is inconsistent with the central repository’s commit history, Git will reject the push and output some error messages
error: failed to push some refs to '/path/to/repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Copy the code
This prevents Han Meimei from directly pushing local updates and prevents han Meimei’s submission history from overwriting the submission history of the central warehouse. At this point, Han Meimei needs to first pull li Lei’s updated content, and then integrate li Lei’s updated content into her submission history, and then push the operation.
Han Meimei rebase to Li Lei’s submission history top
Han Meimei can use Git pull to merge upstream changes into local commits in a local repository.
git pull --rebase origin main
Copy the code
The rebase option tells Git to place all han meimei’s local commits at the top of the main branch. After synchronizing with the central repository, the top of the main branch is the top of the remote repository’s commit history, as shown below:
If you don’t add the –rebase option, just use the default pull command. But this will leave a redundant merge commit record in the commit history. In a centralized workflow, it is better to use the Rebase approach rather than generate a merge commit, which makes the commit history look cleaner.
Han Meimei resolving merger conflict
Rebase works by moving local commits to the top of the updated main branch, repeating the process multiple times for multiple local commits. This means that you need to resolve each commit’s local conflicts with the main branch one at a time during the rebase process, rather than resolving the entire conflict with the main branch after a bunch of commits are consolidated together, as is the case with merge commits. This process keeps each commit more focused and makes the project’s commit history clearer. This, in turn, makes it easier to find out which commit the bug was introduced in, and if we have to roll back, we can roll back a specific commit to minimize the impact on the overall project.
If Han meimei and Li Lei develop unrelated features separately, there is usually no conflict during rebase. However, if a conflict occurs, Git will pause the rebase current commit process and print the following information, which contains the information needed to resolve the conflict:
CONFLICT (content): Merge conflict in <some-file>
Copy the code
At this point, Han meimei runs the git status command to see which files are causing conflicts. The output of the command indicates which files are not automatically merged and cause conflicts:
# Unmerged paths:
# (use "git reset HEAD <some-file>..." to unstage)
# (use "git add/rm <some-file>..." as appropriate to mark resolution)
#
# both modified: <some-file>
Copy the code
Then, based on the output above, Han meimei edited the conflicting files according to her own ideas. Once the processing is complete, she can temporarily store the file and then execute git rebase –continue to allow the rebase process to continue.
git add <some-file>
git rebase --continue
Copy the code
That’s all you need to do. Git continues to move new commits to the top of the main branch, repeating the process until one of the other commits conflicts and then suspends rebase.
If you feel overwhelmed by conflicting content during a Rebase commit, don’t panic. Executing the following command will exit the rebase process and return to the state before the entire rebase process began
git rebase --abort
Copy the code
Han Meimei successfully released the new feature
So far han meimei has completed the synchronization between the local warehouse and the central warehouse, and can push the new local functions to the central warehouse:
git push origin main
Copy the code
What is the
Centralized workflows are great for small teams. But as the team size grows, the conflict resolution process used in the above example becomes a bottleneck for team collaboration. If your team is comfortable with centralized workflows and wants a cleaner way to collaborate, you should try to learn about functional branching workflows. By introducing a separate branch that corresponds to a separate function, this is enough to give the separate function ample room to check and adjust before it is integrated into the main branch.
Other common workflows
The first introduction to the seemingly old centralized workflow is based on the simplest workflow that all other workflows are based on. Most popular Git workflows involve a somewhat centralized repository with which individual developers interact with pulls and pushes and the like. Here’s a quick look at some of the other common Git workflows. These extended workflows provide specific resolution patterns for branch management in scenarios such as multifunctional development, Hotfixes, and release version management.
Functional branch workflow
Functional branching seems a natural and logical extension of a centralized workflow. The core idea behind the functional branching workflow is that all functionality development should occur in a proprietary branch, not within the main branch. This encapsulation allows multiple developers to collaborate on a feature at the same time without any impact on the main code base. This also means that the main branch never contains any code completed for development, an indispensable advantage in a continuous integration environment.
Gitflow workflow
The Gitflow workflow defines a strict branching model around the project release process. This workflow does not introduce any new concepts or commands on top of the functional branching workflow. It simply defines how different branches assume different roles, and when and where branches of different roles interact.
Forking workflow
The Forking workflow is different in nature from the workflow described in this article. Instead of using a single server-side repository as a central code base in a centralized workflow, the Forking workflow allows each developer to have their own server-side repository. This means that for each contributor, there is not just one repository, but not two: one private local repository and one public server-side repository.
Recommendations for
There is no Git workflow that fits all teams. As mentioned earlier, it is important for your team to develop a workflow that is appropriate for your team to improve output. In addition to team culture fitness, workflows should also fit the team’s business culture. For example, Git branch and tag management should apply to your business release cycle. If you are still using project management tools to track the project cycle, you may also want to define branches that correspond to the task development process. In addition, here are some factors to consider when selecting a workflow:
Short-term branch
The longer a branch exists, the longer it is isolated from the primary branch, which in turn means the greater the chance of collisions during merging. Keeping the life of branches as short as possible makes the merge process smoother and the result cleaner.
Fine-grained rollback
The important value of a workflow specification is that it proactively prevents fallbacks from happening. One example is testing a branch before merging it. Often, however, there are other reasons for a rollback to occur. In this case, a good workflow should make the rollback process easy and minimize the impact on other team members.
Matching release cycles
Workflow should fit into your business release cycle. If your business cycle requires several releases a day, you need a workflow that ensures that the main branch is always stable. If your business release cycle is not that frequent, you may want to consider using Git’s tagging function to tag a branch for release with the corresponding version number.
conclusion
In this document we discussed Git workflows. Along the way, we took an in-depth look at examples of centralized workflows in practice. It was then extended to other workflow patterns based on centralized workflows. Finally, we hope to draw the following conclusions in this paper:
- There is no absolutely universal Git workflow
- Workflow should be as simple as possible and increase team output
- Business requirements should help you shape your Git workflow