This post was originally published in medium.freecodecamp.org
The code was working yesterday but today it is not
The code got deleted
A weird bug has been introduced suddenly and no-one knows how
If you have been in any of the above situations then this post is for you.
Apart from knowing git add
, git commit
, and git push
, there are a bunch of other important techniques in Git. Knowing these will help a lot in the long run. Here I will be covering some of the things which will enable you to make the best use of Git.
Git workflows
Whenever multiple developers are involved in a project it is necessary to use the right workflow for Git. Here I will be covering one workflow which is very effective in big projects with multiple developers.
Scenario
All of a sudden you have become the tech lead for a project in which you are planning to build the next Facebook. The team has three developers:
Alice: has one year of experience and knows programming
Bob: has one year of experience and knows programming
John: has 3 years of experience and knows programming well
You: assigned as tech lead for this project
Development process in Git
Master branch
The Master Branch should always have a copy of the existing code in Production.
No-one — including the tech lead — should be coding directly in the master branch since it is a copy of production code.
The actual code is written in other branches.
Release branch
When the project begins the first thing to do is to create a release branch for the project. The release branch is created from the master branch.
All code pertaining to this project will be in the release branch. The release branch is just a normal branch with the prefix release/.
Let’s call the release branch for this example release/fb.
It’s possible that there are multiple projects running on the same code base. So, for each project, a separate release branch is created. Let’s say there is one more project running in parallel. Then that project can have a separate release branch like release/messenger
The reason to have a release branch is that the same code base can have multiple projects running in parallel — there should be no conflict between the projects.
Feature branch
For every feature that is built in the application a separate feature branch is created. This ensures that the features can be built independently
Feature branch is just like any other branch but with the prefix feature/
Now you, being the tech lead, have asked Alice to build a login screen for Facebook. So she creates a new feature branch for this. Lets call the feature branch feature/login. Alice would write the entire login code only in this feature branch.
The feature branch is generally created from the release branch
Bob has been tasked with building the “Friend” request page. So Bob creates a feature branch called feature/friendrequest
John’s task is to build the news feed. So John creates a feature branch called feature/newsfeed
All of the developers code in their individual feature branches. So far so good 😃
Now, let’s say that Alice finished her task and the login code is ready. She needs to send her code to the release branch release/fb from her feature branch feature/login. This is done through a pull request.
Pull request
First and foremost, a pull request is not to be confused with git pull
.
The developer cannot push the code directly into the release branch. The tech lead needs to review the feature code before it goes into the release branch. This is done through a pull request.
Alice can raise the pull request as follows in GitHub — these steps are specifically for GitHub.
Right next to the branch name there is an option called “New pull request”. Clicking on this opens a new screen shown below:
Here:
the compare branch should be Alice’s feature branch feature/login
the base branch should be the release branch release/fb.
Once this is done, Alice needs to enter a title and description for the pull request, and finally click on “Create Pull Request”. Alice also needs to assign a reviewer for this pull request. She enters your name as the reviewer since you are the tech lead.
The tech lead then reviews the code in the pull request, and merges the code from the feature branch into the release branch
So now you have merged the code from the feature/login branch tothe release/fb branch and Alice is pretty happy that her code has been merged. 😃
Code Conflicts 😠
Bob has completed his code as well, and has raised a pull request from feature/friendrequest to release/fb.
Since the release branch already has the login code, code conflicts occur. It is the responsibility of the reviewer to resolve these code conflicts and merge the code. In this case, you as the tech lead need to resolve these code conflicts and merge the code.
Now John has also completed his code and wants to add his code to the release branch. But John is pretty good at handling code conflicts. John takes the Latest code from release/fb branch into his own feature branch feature/newsfeed ( either through git pull or git merge ). John resolves all the conflicts that are present. Now the feature/newsfeed branch has all the code present in release/fb as well.
Finally, John raises a pull request. This time there are no code conflicts in the pull request since John has already resolved them.
So there are two ways to resolve code conflicts:
- First method: the reviewer of the pull request needs to resolve the code conflicts.
- Second method: the developer ensures that latest code from the release branch is merged into the feature branch and resolves the conflicts themselves.
In Enterprise projects beginner developers can initially start with First Method and eventually move to the second method. Second method is the preferred method
Master branch again
Once the project is completed, the code from the release branch is merged back into the master branch. The code is then deployed to production. Thus, the code in production and the code in the master branch are always in sync. This also ensures that, for any future project, the up-to-date code is available in master.
References
More information about pull requests is here.
Congrats 😄
You now know about git workflows. Git has some other concepts like amending commits, and rebasing which are also useful. But Git workflow is pretty important for big projects to be successful.
For small projects this workflow can seem to be like an overhead. So other alternatives can be used in small projects.
Top comments (55)
Good post, thank you!
Generally I disagree that the reviewer should solve conflicts. I had to do that and it's the hardest thing on planet when you have not written the actual code.
Conflicts happen when two or more people work in the same sphere. They should be able to handle it. The reviewer should only review the code that works.
Ideal approach is the developers resolve the conflict themselves :).
But that said, if a developer is a beginner, then they will find it hard to resolve conflicts. So in that case the tech lead can resolve the conflicts. With more experience the developer will be able to resolve the conflicts by themselves :)
100% agree. Why should the reviewer be tasked with resolving the conflicts?
I'd not say that GitFlow has real advantages for me, the thing is you might end up with a lot of branch merging which is a real chore and always delays the speed of the development. In practice there is lot more merges b/w branches back and forth if one follow a git flow based approach.
You might consider trunk based development as an alternative.
But the trunk based development doesn't allow me to manage what goes to release, you take what's in trunk branch and create a release from it (few of our product managers just fainted), you never know if your trunk is stable etc.
Merging between branches with git-flow is a chore if you let it be a chore (there are few git-flow scripts/tools that help with it).
Till now haven't faced any issues with gitflow workflow. But in case issues do come will look into implementing something like trunk based development :)
yeah. just a few questions:
A monthly release
Maybe 10 to 20 commits a day max by all devs combined :D.
Varies. 4 to 8 depending on the requirement.
Current approach is to create a hotfix branch directly from master and make the change for high priority bugs. Low priority ones are generally pushed to the next release
There are situations where the codebase is shared between multiple projects and teams. That's one of the reason this approach worked well till now.
Ok. You did not say here. Do you propagate hotfix commits back to dev and release branches ?
Do you make production release immediately once new release branch is created? Do you continue to merge from dev to release after a new release branch is created?
not sure, what you mean. please specify ...
Git-flow:
1) The hotfix branches are cut from master branch and merged back to master and then to develop branch.
2) You do production release when the hotfix branch from 1) is merged back to master.
3) You don't merge develop branch once you cut release branch from it. This release branch is then just for fixes devs create against it directly or with PRs. Release branch in git-flow is used to QA testing and resolving bugs they find to stabilize that release. When it's signed off then it's merged to master and followed by merge to develop.
Hi Richard. I am replying here to both of your comments. All it boils down to the fact that gitflow is hard to maintain. You have many branches that you have to merge back and forth in right order. It's not immediately seen on simple projects but it becomes painful as soon as frequency of releases and quantity of projects piles up. There is more about this here - endoflineblog.com/gitflow-consider...
In trunk based development there is one main branch ( I am not talking here about short leaving features branches and release / hotfix branches that also exist, anyway ... ) which radically simplifies and increasers the speed of development cycle. And trunk branch is always stable, you can read more about this on the mentioned site or other resources.
Yeah TBD has some tradeoffs but they are incomparable with disadvantages introduced by gitflow.
Sorry, but what is hard on following commands to create a release branch and then close it?
gitflow release start "2.10.1"
gitflow release end "2.10.1"
Similar for hotfix branch:
gitflow hotfix start "2.10.1.1"
gitflow hotfix end "2.10.1.1"
Similar for creating short-lived feature or bugfix branch:
gitflow feature start "feat/new-login-page"
gitflow feature end "feat/new-login-page"
Sure, it's one of my scripts that does all the hard work, but I don't need to think about merging...
Sorry again, but people who do write off git-flow because they think it's complicated, they simply don't understand its beauty, sophistication, and advantages. And when you combine it with GitHub Flow (Fork&Pull Request), it can't simply be beaten.
And believe me, with TBD you get your trunk/master messy and unstable if anybody can merge there, I tried implementing that many times.
And I ask you again: How do you manage what goes to release when everybody is merging to one branch whatever and whenever they decide?
Well, the shortcuts you have here is just smallest and easiest part of the workflow, the hardest part is merge branches not creating them. In classical git flow you have 5 types of branches you have to merge and create in specific order and in specific times. If you don't follow the rules strictly you end up with the mess.
While it's probably easy to follow gitflow with small projects and low frequency of releases, it is way too harder to keep this approach with frequent releases and large code base. This is why companies with large code base and frequent releases like Google practice kinda TDB methodologies ( with variations ) instead of gitflow.
It's not true. Pull requests / Code Reviews are still here to fence main code from junior developers direct commits ( though you might not need this with mature teams, anyway )
Also if a build is broken - it's ok, but you have to stop all the current development and make a fix OR rollback - it's what all the pretty textbook stuff devops methodologies teach us. There is no problem with broken build, there is a problem with recklessness about it. Add here automatic tests triggered by CI/CD, pre commits / push hooks tests and you will get even more layer of confidence ...
And last thing:
Actually you do, but not about technical aspects of merging, but about WHAT you merge, even the fact you have no conflicts or resolved ones does not mean the resulted code is right. Don't get me wrong I am not against merging, but merging is still hard ( not technically but logically ), TBD tries to avoid a lot of merging while gitflow upholds.
The same as with gitflow. At some point you cut off from main branch and create release one.
Pretty good. I have one question about a project with multiple version alive (like apache 2.0.x, 2.2.x and 2.4.x) that are developed concurrently.
What strategy should be implemented in a case like Apache HTTPd server, where 3 main versions are maintained? Should we use 3 different repositories, or should we have three master branch (master20, master22 and master24 for exemple?). Is there other options?
Interesting question.
Never worked on any project with multiple active versions.
I am guessing if the development is concurrent on all the versions, and if the versions have different features then its better to have separate repos for them like angularjs and angular.
Again, never worked on projects with multiple active version. It's better if someone who has actually worked on this answers :D
Well, 3 repos if you don't trust your developers they will create their feature/bugfix branches from correct develop branch, and code lieutenants responsible for accepting PRs or merging from and to correct branches.
Otherwise with git-flow and if you develop new features to all those releases, you will need to have 6 branches (master2_0 => develop2_0, master2_2 => develop2_2, master2_4 => develop2_4). Actually, if you want develop new "main" version, you will end up with 8 branches, with additional branches like master-next and develop-next, where you develop new features which are going to next main release, like 2.6.
If you just maintaining those master2_2 and master2_4 branches for security fixes, you should be OK with just master2_2 and master2_4 without develop2_2 and develop2_4 branches and with classic git-flow hotfix branches.
That was basically my concern with one repo, it felt really troublesome for not many advantages. It seems for me that 3 repos are the way to go. The repo is cleaner, less confusing.
Nice post, thanks for sharing!
I have a question, what is the pros and cons of using forks (with branches) instead of new branches in the "upstream" repository?
Regards,
-Pablo
Thanks you
Generally in open source projects you would fork the repo, make your changes and then raise a pull request to the original repo. The reason for this is that you would not have write access to the original open source repo. Unless you have write ( collaborator ) access you cannot create branches in the original repo.
What I have explained in this article in a branching strategy which can be used provided you have write access to the repo :). This is easily applicable to enterprise projects.
Yes, I know that, on the company I'm working I always recommend to fork the project and then work on the forked one, the devs don't have write access to the original repo, I like to keep clean the original repo and only have the branches I (or the Technical lead) want to keep.
For me the Pros i found:
Cons:
What do you think? you add more pros and cons?
Thanks for your time, regards.
-Pablo
Thanks for mentioning them :)
You have pretty much covered the pros and cons. Here Will list out some more as well
Pros of forking:
The dev's do not need to worry much about breaking the code by mistake Since they wont have access to the original repo
cons
as you mentioned, it can be more time consuming to update local code
But I did come across branch level permissions as well. So one thing which can be done is only the tech lead and some senior devs have write access to the master and the release branch.
All the other developers will have complete access to feature branches, but a read only access to master and release branch. This will ensure the code in master branch and release branch are reviewed and tested code
What do you think about branch level permissions instead of forking in enterprise projects?
Open source I guess forking is the way to go, Since there will be an explosion of branches if every single open source developer gets their own branch in the original repo :D
Agreed with you, I'm currently thinking on what is the best approach using fork or branch access on upstream.
As you say OS project is the way to go, but I'm thinking if we will use fork or branch, due the ore junior devs have a lot of issues when they need to update the code :/
Thanks,
-Pablo
Either one should be fine :)
Use the method the team is more comfortable with :)
Sorry, but this "It is the responsibility of the reviewer to resolve these code conflicts and merge the code. In this case, you as the tech lead need to resolve these code conflicts and merge the code." is fundamentally wrong and that's not how Pull Requests work.
Before any Pull Request can be merged it has to have resolved any conflict with code in target branch (I believe GitHub wouldn't allow merge before the conflicts are resolved). And that is PR author's, no matter if begginer or senior, responsibility. This has been workflow for Linus, for GitHub and its clones, actually everybody for years.
What you are saying is absolutely right for open source projects :)
But in enterprise projects, in case the developer is a beginner , it is better if the tech lead resolves the conflicts. Over time with experience the developer would learn how to resolve conflicts.
I guess i haven't mentioned that clearly in the post. Thanks for pointing out. Will make that more clear in the article
What I have written is valid for both, open-source or enterprise...
If you developer is a beginner, he can ask somebody to help him with resolving of conflict which is anyway on his branch, not on develop branch. If the TechLead will always resolve those conflicts, those kids will never learn how to do that and would always dump that conflict on Tech Lead. Bad idea...
That is a valid point :)
Maybe the right way of putting it in the article would be "The Tech lead can resolve the conflicts in case the deadlines are tight. But best practise is to ensure beginner devs take the help of someone to resolve conflicts so that they learn the process as well"
it’s easy to ready
thank you :)
thanks. Happy it is easy to read :)
Nice post!
But i do hv a questions on feature -> release
in one of my new project
i expect some features will only be POC and may never implement into production
but user still want to test it first
my current approach is to create a develop branch which act as a UAT environment for user to test out features if feasible or not and only merge into release if they feel good about it
is it a good approach or not?
Thanks!
I Have been in similar situations :D
I did exactly what you have mentioned.
The only catch is that it works very well for independent features. But if you have dependent features then we had to deal with it by manually changing the code. Still figuring out the best way of handling this
actually i think there may be a issue..
variation of
develop
andrelease
will become greater and greaterand at some point, we may be forced to merge
release
intodevelop
just to get things a bit easier to work with..
hv any ideas about it?
maybe rebase can do the trick? but im not familiar with it
Rebase is generally used to update the code in local with the latest code in remote. Using Rebase in the remote can create issues since it overwrites history.
I have written about rebase as well. You can check it out here
adityasridhar.com/posts/how-to-bec...
I guess one option is to handle it in the code itself rather than trying it with git. You can have a config to say which features to enable and disable.
So when users say they don't want a feature, you just go to the code config and disable it. In the future, they may want the feature back. In that case go to the config and enable it :D
I think having a config like that makes it easier than handling it with git. What is your take on this?
omg😲
using config file is a brilliant idea!
why i hvnt thought of this before!
i know rebase will overwrite the history, maybe i will just stick to local rebase first
Thank you!😘
One more thing I’d add is make sure the expected git flow is documented. I’ve found that devs will have their own ideas on branching and before you know it you have 3 different naming schemes going for branches. You can explain it once, but they will forget or go back to their way after a long weekend. Great article!
Document? What's that?
Good point. Yes it needs to be documented :)
There is another method for developer to resolve conflicts, namely rebase his or her changes on top of the current state of main line of development (with interactive rebase the developer would also be able to clean up history to make for easier review). When doing a pull request from rebased branch, it should be able to be merged cleanly.
Yup. I Have written about rebase in this article
adityasridhar.com/posts/how-to-bec...
Will soon post it in dev.to as well
Thanks for this outstanding article.
Actually, in my current company we're implementing Git workflow and it is a good material to my coworkers.
Regards from Ecuador
Happy it helps :)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.