Skip to content

[github] Branching and merging to dev using rebase

Utumno edited this page May 18, 2021 · 25 revisions

First a heads up.

You should Never, Ever push directly to the dev branch. NEVER. Umm, never.

So you have to create your branch and push this. Your branch is your branch, you may delete it, rewrite history, merge commits, split commits (in case of doubt, prefer keeping commits separate - squashing commits together after a review is painless, splitting a commit into multiple can be painful) - the later three with rebase -i, which is a console thing and not a GUI one.

You can create a new branch via the console:

$ git checkout -b utumno-163-wip

The bad thing with this is you do not have a clear idea of where exactly the branch is in the tree. Enter gitk (comes with git):

add branch in gitk

Give it a nice name, check it out (right click on the branch name > checkout this branch) and start committing

Setting up your branches

The standard procedure for contributing to the repo is branching off dev, whether you do it from your fork or you have write rights in wrye-bash/wrye-bash

$ git checkout dev # local branch set up to track remotes/origin/dev
$ git checkout -b devname-branchname

devname is your username in lowercase

Get in the habit of rebasing your branches over dev frequently. This way you take latest fixes/features in, plus, in case conflicts arise1, you spot them early when they can be resolved more easily. So if you have:

  • Upstream

      dev A - B - C - E	# E is a new commit added since you branched off
    
  • Locally (git checkout dev):

      dev* A - B - C
                    \
      devname        D - F
    

To easily rebase:

$ git checkout dev
$ git pull # take in upstream changes
	dev* A - B  - C - E
		       \
	devname         D - F

Issue: git rebase -i --onto dev C devname to get:

	dev A - B  - C - E
			   \
	devname*             D` - F`

Do this often, even if no changes are made upstream, to cleanup your commits (see our tips page for setting up an editor). However never rebase branches you've pushed and other people have used.

Avoid unnecessary pull requests - just notify one of the releasers team in the relevant issue or by mentioning them in a commit note when your branch is ready to be merged.


Merging to dev (for wrye-bash/releasers)

Never merge pull requests to dev - always rebase merge. That keeps exactly and only the needed history, produces a clean tree topology and puts the code merged to context as pull requests are usually reviewed when merged not when submitted.

A mixed up tree leads to real bugs as for instance 305 displaying its version number as 304.4. So be sure to grok what follows:

Wrong :

  • Merge (git merge devname --no-ff):

      dev* A - B - C - D'	# D' is your merge commit - due to --no-ff in this case
                    \ /
      devname        D
    
  • Pull dev that is fetch and merge (git pull):

                      E --- 
                     /      \
      dev* A -  B - C - D' - E'	 # E' is the merge commit of your local dev branch and upstream one !
                     \ /
      devname         D
    

So that's a mess.

Correct way :

$ git pull # be sure to pull dev also
$ git checkout devname
$ git rebase dev

After those you have

A - B - C - E
	     \
	      D'   # notice the ' - it is not the D commit anymore, but has
	           # the same changes plus any conflict resolution

your branch is "rebased"2 on the HEAD of dev - hence this command's name.

Then merge devname to dev (if passed review) and push A B C E D' if D' is a single (couple small) commits or merge --no-ff if D' is a series of commits you want to preserve history of - in this case you'll end up with:

	dev* A -  B - C - E - D''	 # D'' being the no-ff merge
			   \ /
	devname             D'

tl;dr

# when ready to merge
git checkout dev
git pull # take in upstream changes
git checkout yourbranch
git rebase dev # ALWAYS, you may run to conflicts (you would not avoid anyway)
git checkout dev
git merge yourbranch [--no-ff] # use --no-ff when you want to preserve the branch - not for
# trivial branches with a couple of commits

1: mostly due to working on the same code area as the current dev commits, but you should take the opportunity to also check your new code compatibility - for instance a function you use might have changed signature

2: this is the point when conflicts may arise - good luck (and don't forget rerere and git config merge.conflictStyle diff3)

Clone this wiki locally