View on GitHub

Git-Process

Scripts to help work with a streamlined Git process

Download this project as a .zip file Download this project as a tar.gz file

Purpose

This provides an easy way to work with a sane git workflow process that encourages using highly-focused branches to encourage collaboration, enable fearless changes, and improve team communication.

See the F.A.Q. for a much more complete explanation for the thoughts and assumptions that motivates this project.

Installation

Unix-based OS (OSX, Linux, etc.) Installation

$ sudo gem install git-process

Some older operating systems (such as OSX 10.6) are using an old version of RubyGems, which can cause installation problems. Do "sudo gem update --system" to fix.

Windows Installation

  1. Install Ruby (if you have not sone so already) from http://rubyinstaller.org/
  2. Open a command prompt and type gem install git-process

Overview

Anticipated Use Cases

  1. User creates new local branch for focused work.
  2. User pushes local branch to remote (as feature branch) by merging/rebasing with the integration branch, then pushing to the branch to remote.
  3. User closes local branch by rebasing integration branch first, then pushing local to integration.
  4. User initiates GitHub "pull request" to ease collaboration.

Command List

All commands are well documented within themselves: Use the "-h" switch to see the full documentation. (e.g., "git sync -h")

Workflow

The following assumes that the integration branch is "origin/master".

Code Review Using Pull Requests

  1. When starting work on a new feature, use "git new-fb feature-name".
    • This creates a new branch called "feature-name" based on "origin/master".
  2. After making some changes, if you want to pick up any changes other people have made, as well as save your work on the server, do "git sync".
    • That will merge in the changes that have occurred in "origin/master" and then push the result to the "feature_branch" branch to the server.
  3. When you feel your work is ready for others to look at, do "git pull-request" to ask someone to review your changes.
    • If no name or number is provided, it is assumed that you want to create a new pull request with the same name as the current branch.
    • Any changes you make via "git sync" are automatically reflected in the pull request.
  4. As a reviewer, to see a pull-request, do "git pull-request ##" (where "##" is the pull request number) to check out the branch associated with the pull request in your repository.
  5. If you get the thumbs up from the code-review, use "git to-master".
    • This will merge and push your changes into "origin/master", closing the pull request.
    • If reviewing the pull request via the web interface was sufficient, or there is otherwise not a reason to explicitly checkout the branch first, you can use "git to-master" with the pull request number to combine both of these steps.
  6. If you still need to make changes, do so and use "git sync" to keep your branch on the server for that feature updated with your work until all issues have been resolved.
$ git new-fb my-feature      # 1
# do work                    # 2
$ git commit                 # 3
$ git sync                   # 4
# repeat #2-#4 as necessary  # 5
$ git pull-request           # 6
# repeat #2-#4 as necessary  # 7
$ git to-master              # 8

Working Alone or When Pairing

  1. When starting work on a new feature, use "git new-fb feature-name".
    • This creates a new branch called "feature-name" based on "origin/master".
  2. After making some changes, if you want to pick up any changes other people have made, as well as save your work on the server, do "git sync".
    • That will merge in the changes that have occurred in "origin/master" and then push the result to the "feature_branch" branch to the server.
  3. When you are ready to merge your work into the mainline, "git to-master".
    • This will merge and push your changes into "origin/master"
$ git new-fb my-feature      # 1
# do work                    # 2
$ git commit                 # 3
$ git sync                   # 4
# repeat #2-#4 as necessary  # 5
$ git to-master              # 6

Configurables

(See Notes for more details)

Assumptions

Notes

F.A.Q.

Q: How is this different from git-flow or GitHub flow?

"git-flow" is designed around having a very strongly defined process around keeping new development, hotfixes, release process changes, etc. all clearly separated. The problem I have with it is that it's too much "process" for not enough gain. (It has a waterfall feel to it, very much against the more modern Continuous Delivery approach.)

"GitHub Flow" is a lot cleaner, but relies too heavily (IMHO) on web-based tools and on merging instead of rebasing. It is also focussed very tightly on a Continuous Deployment process, which is great for them, but not practical for everyone.

Q: Wait, I heard "branches are evil." Why should I do something evil?

Branches are extremely powerful tools that allow for clean organization/modularization of development.

Jez Humble, a brilliant Principle at ThoughtWorks Studios, talks a lot about how "branches are evil." Unfortunately, people hear that, know how smart he is, and simply repeat it without really understanding what his objections are. Fortunately, he posted clarification about what's really meant by that. He essentially says that the problem is that developers abuse branches by not merging with mainline (i.e., "master") on a regular basis. Not constantly getting changes from mainline makes life rough when it comes time to integrate. Not putting your changes into mainline means that your changes are not being validated (via Continuous Integration, or -- better -- with Continuous Delivery). Both are, in fact, sins akin to not doing automated testing.

Making it "easier to do things right than wrong" (i.e., using branches and keeping them synced with mainline) was the primary motivation for this project. This should be especially evident in the "git sync" and "git to-master" commands.

Q: Why so much emphasis on rebasing? Isn't rebasing a dangerous lie?

Like any powerful tool, "git rebase" is "dangerous" if used incorrectly, just like "rm"/"del". You simply need to know when and how to use it safely. And in the world of version control systems, "rebasing" is easily one of the most useful tools to come around since the "commit" command.

A famous article that people have been parroting in various forms for a while makes the case that rebasing (and its various forms, such as squashing, amending commits, etc.) is a "lie." As with so many things, context is everything.

You almost certainly should not rebase things that you have "published." Generally this really means "Don't rebase the 'master' branch!" Fortunately, these scripts make it impossible to rebase the mainline by accident. By default "git sync" uses "merge" instead of "rebase" to encourage collaboration. (Though you can easily use "-r" if you know no one else is working on the branch.) When it's time to actually merge your work into the mainline (and thus no one is working against it except in the context of mainline), that's when it gets rebased in.

Rebasing "your" code is an extremely useful way of communicating clearly. In the "green to green" scenario above about branches, a lot of noise is generated. If someone wants to review my code, or cherry-pick in my changes, it's too much of a mess to effectively do so. Also, as part of the process of squashing, I have the opportunity to write clearer commit message based upon my newly enhanced understanding. The intermediate commits were my "drafts" and I'm now submitting my cleaned up copy.

If you have ever seen an "active" project that uses a process like "git-flow" that encourages a lot of branching and merging, you've seen how hard it can be to follow a particular line of development. Branch lines are flying around everywhere, and half the commits are pretty much pure noise. (e.g., "Merge branch 'develop' of ... into develop".) It's also hard to follow the order in which commits actually impacted the mainline. In many ways, in practice merges turn into "a truth effectively being a lie (because it's buried in the noise)" versus rebases that are "a lie (changed from it's 'original' form) to tell an effective truth (clean and very clear about its impact)."

This project is trying to promote clear communication about reality as it applies to the code, over micro-management over no-longer-relevant history. Thus rational for the judicious use of rebase.

Contributing

Coding Setup

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature origin/master)
  3. Commit your changes (git commit)
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

or, if using these scripts:

  1. Fork it
  2. `git new-fb my-new-feature
  3. git commit
  4. git sync
  5. git pull-request

License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.