Git merge strategy
We have a project hosted on Github with a main development branch called “Master”.
Some developers tend to merge project branches into Master. And others tend to merge Master into project branches.
Seems to me that the former adheres standard protocol. The later just doesn’t make sense. Am I just being paranoid, or does it really make a difference?
To compound things, the project branches are then being pushed back to github with the merged Master branch
For those that merge Master into project, the argument is that they need to an up-to-date copy of Master. My answer; what does a merge have to do with it? Maybe to pick up changes that have been introduced by others and merged into master?
Shouldn’t the process be:
1) checkout master,
2) git fetch or git pull
4 Solutions collect form web for “Git merge strategy”
It makes total sense for the developers to merge the master branch into their project branch every now and then to make sure that they are not doing things that will not work once merged. This usually happens in their local repository.
Then, when they are done with the new feature, they merge it into master, and push, which will add that feature to the master branch of the public repository. Or they just push what’s in their feature branch to the master branch of the public repository.
git fetch is just a way to fetch a repository from some remote. It will never do a merge at all. A
git pull will do the same thing, but also includes a merge.
So the process that you are suggesting will at best only merge changes to the public master branch with the local master branch. The developer will then still need to merge their local (now up-to-date) master branch with their feature branch or they will not be able to perform the sanity checks mentioned above.
In contrast to @richardolsson, I wouldn’t recommend that they merge master into their topic branches, if by merge we mean
git merge master.
It is definitely a good idea for them to take updates that have happened on master and update their topic branches to reflect those changes, so as to avoid everything breaking terribly, but git provides a bit of a better tool for this particular use case,
Conceptually, they are very similar and the outcome in terms of the codebase is often identical, however using
rebase can make the history of the project much clearer to someone looking at the logs, and help keep from having a gigantic history graph to look through, even though those can look pretty sweet.
merge, git takes the status of the two (or more) branches being merged, attempts to piece them together appropriately, and makes a commit reflecting that a merge has happened, unless the HEAD of the target branch is a direct descendant of the branch being merged in, in which case it doesn’t need to do any diff/patch stuff and just plays the commits on top of each other (git calls this fast-forwarding).
rebase, git (conceptually) takes the target branch, goes back to the last commit that it has in common with the branch it’s being rebased on, makes the commits from that branch, and then makes the commits from the target branch. An example may be in order:
You have two branches,
master, with commits
topic, which was branched at
B and has the commits
F. If you are on
git merge master, you can end up with a commit history that will look like
A B E F G where
G is the commit made by merging. If you rebase, git first takes
topic and makes it’s commit history the same as
master, and then makes the commits in
topic, so you get a commit history that looks like
A B C D E F.
One major advantage of doing this, other than the clarity in log history, is that as long as there haven’t been changes in
master since you rebased,
git checkout master && git merge topic or similar will always be a fast-forward, since all of
master‘s history is contained in
topic. The big caveat here is to
not rebase branches that are meant to be publicly shared, because the SHA-1s of the commits have to be rewritten, which basically means a bunch of meaningless conflicts.
It took me a while for the benefit of this to take hold in my head. I’ve since found that (for me at least, and so far…), the “best” workflow is to:
- rebase topic branches
- merge tracking branches
git checkout topic git rebase master # fix any conflicts, run tests, etc git checkout master git merge topic
This gives a very clear history, and pretty much ensures that if breakage happens, it happens on the topic branch. It also makes some of the tools like
git bisect a bit easier to use when you need to use them.
Anyhow, hope you found this way-too-long answer useful.
The better workflow would be, that the developers rebase their feature/project branches on the master branch, to avoid cluttering the history.
The first thing to realize is that branch names are technically only local to any given repository. The central
version-2.0 might be my
master and your
testing. That being said, in practice, people usually use the same names as the repository they most often push to, so merging
master then pushing
master is the standard way.
project will produce this tree:
master A____B project \__C_\_D
master will produce this tree:
master A____B___D project \__C__/
Note that both are essentially identical except for the branch names at
D are reversed, along with the order of its parents. As long as you specify
git push origin project:master if you do it the first way, then update
master to point to
D somehow before making another branch, you won’t notice a difference in practice. However, that’s creating extra mental effort for yourself, and you can screw things up if you don’t do it right every time. Merging
master allows you to set up defaults for
push that make it easy.