Git Workflow: Clarification and Avoiding Antipatterns
I am in the process of developing a Git workflow for a web app project I am working on. I have used Git for several years, but only as a solo developer. I have put a set of procedures together, and yesterday ran across this article on HN: http://sandofsky.com/blog/git-workflow.html
Based on the article I have adjusted my procedures and would appreciate some feedback. I want to make sure I am interpreting the article correctly and not contributing to issues down the road. Based on the article in question, and the desire to provide good working standards, are there any issues with the following procedures?
Basics
- master branch - The main, working branch into which all code development is merged. This represents the most recent additions to the codebase from individual development branches.
- 'dev_' branches - Local, private development branches should be used for developing new features. If you need to push the branch to the server (so you can switch easily between computers) please make sure that the dev branch name includes the user name, like 'dev_andy_authentication'.
- staging branch - Before deployment of certain code from the master branch, the code must be tested in an environment that matches the production environment as closely as possible. Code from the master branch is merged into the staging branch, tested, and, once it passes tests, is eligible for production.
- production branch - Stable code from the staging branch is integrated into the production branch, tagged with a release version number, then deployed to the production server(s).
Development
Branch: master
- Use local, private feature branches to separate code:
- Switch to ‘master’ branch: git checkout master
- Create a new, private feature branch: git checkout -b dev_newfeaturename
- Make feature additions.
- Stage changes: git add .
- Commit changes in ‘dev_newfeaturename’: git commit -m “commit description”
- To integrate changes from 'dev_newfeaturename' branch:
- Switch to ‘master’ branch: git checkout master
- Check for remote changes to ‘master’: git pull --rebase origin master
- If changes in 'dev_newfeaturename' branch are relatively small:
- Integrate changes from ‘dev_newfeaturename’ branch into master: git merge --squash dev_newfeaturename
- Write a detailed commit message of changes implemented from 'dev_newfeaturename' branch: git commit -v
- If changes in 'dev_newfeaturename' branch are more complex, requiring multiple commits to remain in the history:
- Switch to ‘dev_newfeaturename’ branch: git checkout dev_newfeaturename
- Reintegrate any changed ‘master’ code into ‘dev_newfeaturename’ branch: git rebase --interactive master
- To cleanup history by combining commits, change the operation from "pick" to "squash", which squashes the second commit into the first
- Switch to ‘master’ branch: git checkout master
- Push changes to remote ‘master’: git push origin master
- Check for remote changes to ‘master’: git pull --rebase origin master
- Push all changes to 'master' back to the server: git push origin master
- ‘Master’ becomes the working tree of all currently developed features.
- Periodically pull ‘master’ changes from remote: git pull --rebase origin master
Staging
Branch: staging
- Once a release of a certain number of features/bug fixes has been scheduled, ensure that ‘master’ is functioning properly then merge into ‘staging’ by:
- Switch to ‘staging’ branch: git checkout staging
- Integrate changes from ‘master’ into ‘staging’: git merge --no-ff master
- Push ‘staging’ to remote repo: git push origin staging
- Deploy ‘staging’ branch to staging server and test rigorously - staging server should replicate production environment as closely as possible.
- If any testing fails, return to ‘master’ branch, fix any associated issues, and restart the Staging process.
- If all testing passes, proceed to P开发者_如何学Pythonroduction process.
Production
Branch: production
- Once code in the staging branch has been tested and has passed, switch to the ‘production’ branch: git checkout production
- Integrate changes from ‘staging’ into production: git merge --no-ff staging
- Tag code with sequential release version number: git tag -a 0.1
- Push ‘production’ to remote repo: git push origin production
- Deploy ‘production’ branch to production server and test to ensure proper deployment.
You wrote:
If changes in '
dev_newfeaturename
' branch are more complex, requiring multiple commits to remain in the history:
- Switch to ‘
dev_newfeaturename
’ branch:git checkout dev_newfeaturename
- Reintegrate any changed ‘
master
’ code into ‘dev_newfeaturename
’ branch:git rebase --interactive master
- To cleanup history by combining commits, change the operation from "pick" to "squash", which squashes the second commit into the first
- Switch to ‘
master
’ branch:git checkout master
- Push changes to remote ‘
master
’:git push origin master
I think you forget the fast-forward merge of 'dev_newfeaturename
' into ‘master
’:
The rebase allows you to replay 'dev_newfeaturename
' on top of ‘master
’, cleaning up the commits in that process. That is good.
But if you want to push back master to the remote, master needs those cleaned commits in its history: `git merge dev_newfeaturename
Regarding a branch per development state (staging, prod), I wouldn't recommend that approach, unless you are actively producing new commits in those branches.
Remember the sentence about no-ff in the article you reference:
The only remaining argument for
–no-ff
is “documentation.”
People may use merge commits to represent the last deployed version of production code.
That’s an antipattern. Use tags.
精彩评论