1

I know that there's plenty of similar questions, but I couldn't find a good answer that helps me to propose a good solution in the company where I work. We're not a lot of developers, but I would like to propose a scalable workflow.

The (not so) hypothetical case

The situation is the most common one: there is a master branch that never receives direct commits. If I need to do something I create a feature/personal branch (usually long-live personal branches was used more often than fats feature ones). Once I feel comfortable with the code I created, I want to bring it back to master (which, in meantime, has received another commits).

It's important to point up that both master and branchX are always pushed to remote.

So, to graphically clarify it, we are in this situation (I'll use C for commits, M for merges):

branch1 C2---C3---C6---C9--- / master C0---C1---C4---C5---C7---C8

Current Workflow

The current used workflow can be defined merge-up/merge-down: since I don't want to fix merge conflicts in master, first I merge-up master inside branch1, and then I merge-down branch1 in master.

branch1 C2---C3---C6---C9---M1 / /\ master C0---C1---C4---C5---C7---C8 M2

Doing so, I resolve the conflict inside the branch and then I can merge down my branch into master.

Personally I don't like this solution for two main reasons:

  • it leads to a very messy history tree
  • merging a parent branch into a child branch sound so no-sense to me

On the other hand, my coworkers argues that:

  • it's easy to understand, even for not-expert internship coworkers
  • it leads to fewer errors since you left untouched the history (unlike rebase)

Proposed solution

What I proposed is the common and more straightforward rebase-before-merge-down workflow.

Once i want to merge branch1 in master, first I rebase the former on the latter, so i handle all the conflicts in my branch; than I merge-down branch1 into master (with NO-FF if the feature branch is meaningful, with FF otherwise)

branch1 C2---C3---C6 rebase / \ master C5---C7---C8 M1

This solution, however, has a main drawback:

Since both are synced with the remote, a git push --force is necessary. So, if someone do something wrong (because he's in a hurry, distracted or silly), weeks of work could be lost in one second.

On the other hand, the advantages should be:

  • Keep the history tree very clean and meaningful
  • Flatten and remove useless branches, keeping only relevant ones

So, the question?

Which scalable workflow do you adopt in your large team to keep the git history clean and meaningful, and, on the other side, prevent potential disasters like a wrong git push --force can do?

2
  • Have you get the answer which help you solve the problem? If yes, please mark it. And it will help others who have similar questions.
    – Marina Liu
    Commented Mar 20, 2017 at 7:30
  • You're right, I was really busy last week and I didn't find the right moment to answer and mark the solution :) Commented Mar 21, 2017 at 22:03

2 Answers 2

1

One common model in my experience has been this:

  • There is an authoritative master repository.
    • The master branch here can only be updated via pull request (in your parlance, a down-merge).
    • Whether you may force-push to other branches is determined on an ad-hoc basis (tends to be determined by how many people actually need to work on a branch simultaneously).
  • Everyone maintains their own fork of the master repository.
    • They can force-push to their own branches whenever.
    • To merge changes into the master branch of the master repository, you rebase your branch onto master and pull request in.

Releases are much trickier to handle.

I would suggest looking at how open-source projects such as Linux, Git, Node, etc. maintain their repositories and take that into consideration.

1
  • Thank you, pull request could be a viable and straightforward solution, also in the same repository :) Commented Mar 21, 2017 at 22:07
1

If branchX (such as branch1) is works for your own, you can use the way you want: rebase before merge.

If branchX (such as branch1) is works for all developers, you’d better not use your preposed solution, the main drawback as you said other developers will be confused, and they may not find their own changes any more.

There is a way you can use: git merge branch1 --squash. Assume you git log is:

branch1         C2---C3---C6---C9---
               /
master   C0---C1---C4---C5---C7---C8

After you execute git merge branch1 --squash, the git log will looks like:

branch1         C2---C3---C6---C9
               /
master   C0---C1---C4---C5---C7---C8---M1

This makes your master branch looks more clearly. And If you want to develop new features you can checkout feature branches from master directly.

BTW: I need to correct the graph you used in your current workflow. After merge master into branch1, the graph looks like

       C2---C3---C6---C9---M1  branch1
      /                   /
C0---C1---C4---C5---C7---C8  master

After merge branch1 into master, there is no commit M2 to create by default, it only a fast forward merge. Both branch1 and master are point to M1 commit now.

       C2---C3---C6---C9---M1  branch1, master
      /                    /
C0---C1---C4---C5---C7---C8 
1
  • Thank you :) Never used squashed merge, really interesting! However this doesn't help in my situation, since my colleagues want to avoid to resolve merge conflicts on the master branch (that's why they usually merge master in branch before doing the merge of branch in master). And thanks for your correction, you're completely right ;) Commented Mar 21, 2017 at 22:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.