As a developer, I use Git common commands every day, so I’m sure everyone knows what to do. However, there are still many differences between the use of Git in teamwork and personal development. For the technical team, we expect everyone to use standard Git operation process and standard Commit Message. Canonical code style. This will improve team development rate and project maintainability. Today, we will introduce a set of Git operation flow based on Github flow.

fork

First of all, in the case of multi-person collaboration, we usually fork the main repository of the team project to our own hosting space and Clone it to local development, assuming that the hosting address of the team project is:

Github.com/fe/github-f…

There are two fixed branches under the main warehouse project: Master and Develop.


Clone to local:

git clone [email protected]:fe/github-flow.git
Copy the code

Suppose the project address after the main warehouse fork above is:

Github.com/xxx/github-…

The Fork repository is completely your own, and you can make any changes to the repository code and configuration, but unless you submit a pull Request to the project repository and it is accepted, you can merge the code you Fork into the repository without affecting the repository.

You can run the git remote -v command on the console to view the address of the remote repository. The command output is as follows:

origin  [email protected]:xxx/github-flow.git (fetch)
origin  [email protected]:xxx/github-flow.git (push)
Copy the code

It can be seen that the origin of the address is the project address just forked into its own managed space.

We can then set up an upstream address named upstream, which is the address of our main repository:

git remote add upstream [email protected]:fe/github-flow.git`
Copy the code

Add an address named upstream that points to the original project repository address from the previous fork. Git remote -v

origin  [email protected]:xxx/github-flow.git (fetch)
origin  [email protected]:xxx/github-flow.git (push)
upstream    [email protected]:fe/github-flow.git (fetch)
upstream    [email protected]:fe/github-flow.git (push)
Copy the code

The purpose of setting the upstream address is that the local warehouse needs to synchronize the code of the main warehouse and update it to the Origin (remote) warehouse in time after we mention the main warehouse in the form of pull request, so as to ensure that the codes of the local and remote warehouses under their own hosting space are up to date.

To keep your local repository in sync with your upstream repository, run the following commands

git fetch upstream
git checkout master
git merge upstream/master
Copy the code

The next step is to push the local repository to the remote repository:

git push origin master
Copy the code

At this point we can develop locally, and usually we specify:

  • Create a temporary branch on the Develop branch (feat/[name-desc])
  • Bug fix Creating a temporary hotfix/[name-desc] branch from master branch

For the Github Flow process, the Master branch contains stable code that is released to production, and the Develop branch contains code that iterates through the latest code review and passes automated tests.

One caveat: no developer is allowed to submit untested Code or Code review Code directly to the Master or Develop branch.

Feat /[name-desc] and Hotfix /[name-desc] are temporary development branches. After the development is complete, the test passes, and the Code review passes, they must be merged into the Develop and Master branches. When code needs to be deployed to production, merge the Develop branch code into master, and then deploy the Master code into production.

Create a feature branch

When developers iterate on a project feature, they first create a branch based on the Develop branch:

git checkout -b feat/feedback develop
Copy the code

We then iterated A functionality in the FEAT/Feedback branch, committing the code to the local repository. If someone else is working on a B feature on the same project, we will check if the feat/ Feedback branch is partially behind the upstream Develop branch before pushing the local code:

git checkout develop git pull git log feat/feedback.. developCopy the code

If no commit is output, the feat/ Feedback branch is up-to-date compared to the Develop branch. Git merge –no-ff — git merge

git checkout feat/feedback
git rebase develop
Copy the code

This will move the entire work branch to the front of the Develop branch, synchronizing the feat/ Feedback branch with the upstream Develop branch, and finally pushing the code to the origin branch.

git push origin feat/feedback
Copy the code

After the pull request is passed, the feat/ Feedback branch’s code merges, and the commit history splits into the latest Develop branch, resulting in a clean, comfortable commit map.

Submit a pull request

Open a pull request on the Develop branch (feat/ Feedback) of your origin repository to submit a pull request to your upstream repository:


There are three ways to merge Code into the Upstream Github-Flow develop branch once Code Review is approved:


When we click on the Merge pull Request, we see three options. A brief introduction to the usage scenario:

Create a merge commit

When you click Create a Merge COMMIT, all commit entries on the Feature branch are added to the Develop branch and a new merge COMMIT node is generated. Git merge –no-ff — git merge — git merge — git merge –no-ff


Git merge –no-ff git merge — git merge –no-ff Some people may not like this kind of fork out effect, but for many people cooperation projects, you need to be more clear tell your friend: this series is submitted for the same purpose, I do, and I’m at the end of this node is the function of local development, merge to develop branches, completed the iterative development. This way peers can clearly see who made which submissions, making it easier to go back in time.

Squash and merge

If you select Squash and merge, git merge — Squash is used. This command will merge all the commits on the pull request into a single commit on the Develop branch, and the original commit history will not be carried over. Suppose this development makes three commits on the FEAT/Login branch:


After clicking, submit the roadmap as follows:


You can clearly see that our three commits are no longer visible on the Develop branch, leaving only the commit that was generated when we committed the pull request.

The criterion for using squash and merge is whether the history of the branch to merge is meaningful. If you commit on the development branch very casually and do not make a good canonical commit, you can use the squash and merge option. However, in multi-player development of large projects, it is a basic requirement for developers to ensure that every commit makes sense, so it is not recommended to use squash and Merge in team development.

Rebase and merge

When you select rebase and merge, you actually do git rebase. Git rebase splashes all the commit history of the pull request into the Develop HEAD in the original order. It looks like the commit was made at the Develop branch, but the SHA1 value for each commit changes. As a result, the SHA1 value merged into the Develop branch will be updated.


After rebase and merge, the commit roadmap for the Develop branch is as follows:


Git rebase: Git rebase: git rebase: git rebase: git rebase: git rebase: git rebase: git rebase: git rebase Do not perform git rebase on a common repository branch other than yourself. Git rebase essentially abandons existing commits to create new commits with the same content, which are actually different commits.

Of course, using Git rebase comes with some risks, and it is not recommended if you are not fully familiar with the Git workflow. For example, in the process of pair programming, you push your commit to the feature branch of your remote repository, and your partner pulls the code from this branch for subsequent development. If you recommit with git rebase command and pull again, then your partner should integrate your commit before submitting the code. And you have to pull the integrated code he submitted, and the whole process is messy.

Git rebase is dangerous, but you’ll be fine if you only execute base changes on commits that have never been pushed to a shared repository. Therefore, we forked the pull request to our own repository instead of the main repository, where Git rebase is safe.

Git rebase cleans up history only for local changes that haven’t been pushed or shared with others, not for commits that have been pushed elsewhere. For example, the need to use git Rebase before pushing all code and making merge requests to ensure that local commits are referenced at the top of all historical commits is a good fit. But do not perform Git rebase on replica branches outside your own repository.

The three methods of pull Request Merge were described above. For team projects, I recommend to use Create a Merge Commit, which can clearly keep the context of each person’s submission, record what actually happened, and keep it for future reference.

Delete feature branch

Use the pull request merge to delete the remote feature branch that has been added to upstream/ Develop:

Local branch deletion:

git branch -D feat/feedback
Copy the code

Remote branch deletion:

git push origin :feat/feedback
Copy the code

Git push [remote name] [local branch]:[remote branch] git push [remote name]:[remote branch]

Branch synchronization

Upstream merges your code into your local and remote develop branches by using a pull request merge. To ensure that the code under their repository is up to date.

Origin branch = origin branch = origin branch = origin branch = origin branch

git checkout develop
git pull upstream develop
git push origin develop
Copy the code

Create a new Bugfix branch

For urgent bug fixes, create a new bugfix branch based on the master branch for quick fixes:

git checkout master
git pull upstream master
git checkout -b hotfix/fixbug master
Copy the code

After modifying the bug, submit the pull request to upstream/ Master after push, and merge it with upstream/ Master branch after automated test and code review are passed, and deploy the code to production to fix the bug. Send a pull request from the hotfix/fixbug branch to upstream/ Develop, close the Develop branch, and delete the local and remote hotfix/ Fixbug branches. Synchronize upstream code to local and Origin remote again the next time you develop the functionality.

Conflict situations arise

If two pull request operations modify the same file and both new feature branches are pulled from the same branch. One of the pull requests is merged into the Develop branch, and a conflict occurs when the other one is merged.


Assume that the conflicting branch is feat/delete and upstream/ Develop is feat/update. Resolve the conflict on feat/delete.

git pull upstream develop --rebase
Copy the code

You can continue as prompted by the console output

First manually modify the code, resolve the conflict after saving the execution:

git add .
git rebase --continue
git push origin feat/delete -f
Copy the code

Feat /delete (feat/update) feat/delete (feat/ Update)


Pair programming

Active situation

Develop (feat/ JIA) develop (feat/ JIA) develop (feat/ JIA) Therefore, pair programming is required at this time. After a develops the common part, he pushes it to his remote warehouse. At this time, he does not submit the pull request. Party B will continue to develop the code of Party A and submit the pull Request to upstream warehouse when it is finished. Examples are as follows:

For example, the remote repository for fork to its own managed space is:

[email protected]:jia/github-flow.git
Copy the code

At this point, A pushes his code to his Origin remote feat/ JIA branch, and then A tells B that you can continue development,

The branch that B plans to develop is Feat/Yi. Perform the following operations:

git remote add pair [email protected]:jia/github-flow.git
git pull pair feat/jia --rebase
Copy the code

Create a remote repository named pair at address a. Then pull the feat/ JIA branch under the repository to synchronize to the current branch.

After modifying the code submission on this branch, B sends the Pull Request to the FEAT/JIA branch of A. If no problem exists, merge the two branches using Rebase and merge. After the code review is approved, Party A submits the pull request to the upstream Develop branch of the repository again and merges it into the upstream DEVELOP branch. Now the feat/ JIA and feat/ Yi branches of A and B can be deleted.

Passive situation

If after submitting the pull request, a finds a problem in code review, but cannot fix it immediately and may need help from others, then B will appear to put out the fire. First, B will pull a feature branch from develop. Pull a feature branch, for example:

git remote add pair  [email protected]:jia/github-flow.git
git pull pair feat/jia --rebase
Copy the code

After b modifies the code, he will pull request the modified content to a’s current feature branch with problems. User A needs to rebase and merge the pull request submitted by user B to branch A. Then follow the standard process to merge the last problem-free pull request into Develop.

supplement

Notes and suggestions for development:

  1. Normalize the Commit Message:

To ensure that each commit is meaningful, developers need to make their commit formats uniform and easy to read. Cz-cli is recommended for the COMMIT specification. The installation steps are as follows:

npm install commitizen -g
Copy the code

Run from the command line in the project:

commitizen init cz-conventional-changelog --save-dev --save-exact
Copy the code

Each commit, run git cz


2. For upstream repositories, protect the Develop and Master branches and do not allow team members to push code to the Develop or Master branches. 3. Set the Develop branch to default so that the Base branch is automatically the Develop branch when the Pull request is submitted. Github flow allows you to configure Webhooks to automatically trigger the release of test environments and automated tests. Only automated tests and code reviews that pass are allowed to merge into the Develop branch. 5. Add some keywords to the description text of the pull request, such as close issue #4. After the pull Request merge is merged into Develop, the issue is automatically closed.


6. Set the pull_request template to normalize the contents of the pull request. The following is an example template:


conclusion

Above is a brief introduction to the Github Flow workflow that I use in my work. However, as I was not familiar with the whole Git process at the beginning, I used to rely on Sourcetree very much and only dared to carry out visual operations on Sourcetree. As a result, I did not have a good understanding of Git workflow. Therefore, it is very troublesome for beginners to start using Sourcetree operations without knowing how they work. Therefore, it is recommended to get away from sourcetree and practice Git’s entire workflow.

This article does not go into the specifics of each command, but rather describes the workflow. If you have any questions about the command, you can use the search engine to learn more.

Finally, as much of the content of this article is personal understanding, it is inevitable that there will be inaccurate or suspicious places, if there is any mistake, welcome to correct.

Related links:

Understanding the GitHub Flow

About merge methods on GitHub

geeeeeeeeek/git-recipes