

Visualized Git practices for team: branch, merge, rebase - kentnguyen
http://kentnguyen.com/development/visualized-git-practices-for-team/

======
martco
I agree with the author that learning and becoming handy with git cli is very
important.

I don't agree that you should stop using a GUI for git, especially if you've
already cut your teeth on the command line. Tower, a git GUI for Mac OS X, has
a great interface and ties in very well with the core git functionality. I've
learned a lot about stashing, merge conflict resolution, and cherry-picking,
thanks to that app. Also, Tower shows a tree graph, similar to the network
diagram the author "seriously cannot live without."

Why knock visual tools when when you rely on them so much?

~~~
alinajaf
I've tried a number of gui tools for git but I keep coming back to the command
line. You can format your `git log` output to give you your network graph and
`git add -[pi]` allow me to stage hunks of diffs much like a GUI tool might.

I think more than what tools you use (gui or command line) it's really useful
to get an understanding of gits internal model. It informs day-to-day use and
is a great example of an elegant, well-designed system.

~~~
palish
_You can format your `git log` output to give you your network graph..._

Really? Awesome. How?

~~~
tednaleid
This is the alias I use in my `.gitconfig` for running log with graphical
output (got this somewhere, not sure where):

    
    
        [alias]
          l = log --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cblue[%an]%Creset %Cgreen(%cr)%Creset' --abbrev-commit --date=relative
    

The omglog gem is also useful for working with git. It gives you a graphical
log of the entire repo (not just your current branch as a normal git log
does), and it auto updates by monitoring for file system changes (OSX only).

To install:

    
    
        sudo gem install omglog
    

Then just run `omglog` in the root of your repo, or use this alias in your
`.gitconfig` to automatically run it from the root of whatever repo you're in:

    
    
        [alias]
            omg = !omglog
    

(shell commands, starting with a "!" command in a git alias are always run
from the root of a repository)

------
spitfire
Isn't it a little ambitious to call yourself a veteran $foo programmer when
you've been doing it for a little over a year?

Particularly when the blog post before this is discussing how .m and .h files
totally confused you. God help him if he gets asked a linked list question in
an interview.

------
gavingmiller
The OP gives his own definition for rebase: git rebasing is taking all your
local changes since the last push and put them ahead of other people’s changes
regardless of the date you made the commit.

But fails to explain _why_ you'd want to do that. Can anyone fill in that why
for me?

~~~
Davertron
My understanding is that it keeps the history cleaner at the expense of being
"historically correct". It's cleaner because you have fewer merge commits, but
less historically correct because it makes your commits look like they
happened after the commits pulled in by rebase.

Personally, I use merge (with --no-ff) vs. rebase. The only time I actually
use rebase is to squash a series of (unpushed!) commits on a feature branch,
and I usually only do that if I went hog-wild, committing more than necessary
while experimenting.

~~~
wanderr
It keeps the upstream history cleaner at the expense of being _locally_
historically correct. In my opinion the nice thing about having everyone
rebase onto upstream is that when their changes get merged into upstream,
upstream's history shows an accurate linear representation of when a piece of
code was accepted into upstream, which to me is far more important than having
an accurate local history.

~~~
Davertron
Great point. One of the more confusing things about looking at the upstream
logs when not using rebase is that they are (by default) in chronological
order. It does seem like it would be more useful to have commits upstream show
in the order they were merged in.

------
igorgue
I think the best thing I did for my team is explain them how branches work,
and how not-so-special are they, branches are just pointers to a commit, and
commits are never 'lost'.

People need to understand how simple Git is.

------
dqminh
Its opposite for us. At work, we dont use branch, only git pull --rebase on
master. Any idea on when and why to use branches often ?

~~~
fhwang
Branching can often be a good strategy if you have a large team and you don't
want large uncompleted chunks of work to block quick fixes & deploys, etc. The
situation you want to avoid is:

1\. Engineers A & B are working on a medium-sized story that's not really done
yet, but is in master anyway 2\. Somebody discovers a small but critical bug
in production 3\. Engineer C can write a bugfix very soon, but can't deploy it
to production because the other story isn't done yet.

But if your team never ends up saying "I'd deploy that but master isn't clean
right now due to different changes", you probably just don't need to branch
that much. Maybe your team is smallish or maybe you're capable of always
breaking up work into really small increments. It really depends on
everybody's situation.

Github does something sort of like this internally:
<http://scottchacon.com/2011/08/31/github-flow.html>

Branching is more overhead in some circumstances but I've also found they can
make things much easier. But I also wish that more people were comparing
strategies and trade-offs because this stuff gets subtle and there are really
lots of ways to do it.

~~~
dqminh
We faced this situation before. What we do is: \- When there is a feature that
is not done yet, but has some user-facing code, we use feature toggler to
disable it on production \- we deploy quick fix by doing a cherry-pick

We discussed about branching a while ago to solve this problem more
effectively but still not satisfied with the pros vs cons. For us, branching
only makes sense if we switch to use branching completely, and thats quite a
big change.

~~~
fhwang
Yeah, personally I know a number of solid devs who like feature toggling but
the notion has always rubbed me the wrong way. Especially because half the
time I'm adding a non-trivial feature, I'm always semi-refactoring the code
underneath to deal with the common patterns and concepts that emerge as a
result of that addition. But I'm a big refactoring-as-you-go kind of person--I
don't know how common this is.

Branching is definitely a significant investment for a team. It's best done
when you've got somebody in-house who can guide everybody through the
etiquette and how to use git to best support it. And if you want to do it all
the way then you want to support in multiple places in your development stack
-- QA servers, staging servers, CI, etc.

But for large units of work that genuinely should stay out of master -- large
user-flow rewrites, big code refactorings or database migrations -- I find it
a great way to have significant experimentation off to the side and then bring
it back into master when it's ready for prime-time.

~~~
sandGorgon
this was a question I had - how do you have your QA,testing,staging setup to
test branches ? Or is fast and frequent commits (by design) eliminate the need
for the commit-deploy-test cycle and replace it with a review step instead ?

~~~
fhwang
Generally speaking I like to have at least one CI environment available for
every branch that makes you nervous, plus master. So what number you're
dealing with depends on the team. Sometimes you have eight engineers but only
four of them are doing something major at any given time.

Of course, whatever you call what you deploy to production -- master,
production, timestamp tagging, etc -- it should ideally pass CI before getting
deployed as well. And there are merge conflicts to deal with, too -- that
ideally belongs to whoever's doing branching.

So, maybe my ideal workflow looks like this:

    
    
      * Branch away from master
      * As you work in your branch, grab a CI server if you feel like it (telling
        everyone else)
      * Commit code in your branch, keeping an eye on your CI as you go
      * Periodically merge in from master, dealing with merge conflicts in your branch,
        *not* in master
      * When you feel like it's ready to go, get whatever review you feel like you
        need -- code review, product manager review, etc
      * If you feel 99% certain it's good, merge it into master and push that back to
        origin
      * Wait for master CI to pass
      * Deploy to production
      * Beer
    

From an etiquette point of view, there are things that can go wrong, not least
the individual commitment to deal with merge conflicts before they get
involved in master. And conflict resolution cannot be rushed. If you have
engineers who are just gonna edit files randomly to get git to accept their
merge, you're going to have problems. (But if you have those sorts of
engineers, you already have problems.)

------
SeoxyS
Can somebody explain how rebasing affects shared histories. Say I'm rebasing a
feature branch that's shared via github, will rewriting the commit history
prevent me from pushing?

I avoid `git commit --amend` because of that, and thought that `rebase` had
the same problem. So for that reason, I always use `merge`. Am I mistaken?

~~~
logophobia
No, you are absolutely right. History rewriting is fine if you do it on a
private branch, but on shared branches it can be problematic.

If there are updated refs on a shared branch, you need to use the --force flag
when pushing, overwriting the previous refs. All the other people pulling will
also need to use the --force flag to get their refs updated.

It could also lead to data loss on all the repositories that do this if
something goes wrong. And it forces other team members to use the correct flag
when pulling and otherwise dealing with cryptic error messages when they don't
do this.

\--amend is fine if you haven't pushed yet, otherwise it has the same problems
as rebase for shared stuff.

------
hack_edu
I love git. It helps me to wake up in the morning some days. But...

The OP's attempt to visualize git concepts falls quite short. This same old
branching graph does little to nothing to illustrate these concepts. I cannot
tell you how many friends and colleagues threw up their hands when someone
tries to graph it out these way.

------
nazri1
The merge-often strategy that the OP recommend in his post is the one that is
Linus abhors so much. He even calls it "unholy mess" :
<https://lkml.org/lkml/2012/1/10/267>. Basically that merge strategy can
produce pointless merges.

See this discussion: [http://git.661346.n2.nabble.com/Re-Regulator-updates-
for-3-3...](http://git.661346.n2.nabble.com/Re-Regulator-updates-
for-3-3-td7174179.html) on the git developer mailing list for more details on
why that merging strategy is not liked.

~~~
lnguyen
The strategy isn't the issue. It's whether it fits with the process you've set
up.

If you do code-review on the contributions/pull requests then I can see where
the merge-often strategy causes issues. The auto-generated merge commits don't
give you the context of the updates that are pulled in and will lead to having
to spend time going back through the commit tree. It may not lead to the
introduction of issues or regressions but you can't be sure.

However, if you're set up as a small team with good internal communication or
a high level of trust, then merge-often can be a good thing in that you
usually aren't left with big merge issues to deal with and you're more likely
to have any conflicting updates fresh in your mind.

~~~
lucisferre
We solve the problem with rebasing. If it's not part of the main branch then
it's not part of history, so rebasing to organize the pull request makes
sense.

~~~
lnguyen
Rebase works great when you need/want to preserve he revision history. It's
probably the ideal process to put in place if you can mandate it.

One thing to keep in mind is that it might lead to a number of merge conflicts
that may be difficult or tedious to resolve depending of how the branches have
diverged. Merging may avoid these.

~~~
lucisferre
Why would regular merging avoid this more than regular rebasing? The result is
the same.

------
lucisferre
His opinions on not rebasing onto master and instead merging are his own.
Personally I find merging far more confusing in terms of understanding history
graphs and always rebase before issuing a pull request. I think you will find
that generally a lot of open source projects on Github have this practice of
asking people to "please rebase your changes onto master so I can merge".

One practical reason is when doing bisects.

There are certainly two schools of thought on this, but "this is confusing to
me so don't do it" shouldn't be considered a valid opinion.

