2010年12月17日星期五

Mercurial workflows: Use REBASE to replace MERGE

Mercurial workflows: mainline workflow



The simplified workflow

In the simplified workflow, it is nearly identical to the normal centralized
workflows (except most operations are local).  When I want to start work
for the day, I’ll:
  • work work work
  • hg commit –Am “Working on some stuff”
  • work work work
  • hg ci –Am “Working on some more stuff”
  • work work work
  • hg ci –Am “Finished my stuff”
At this point, I’ve finished some logical set of work, and I’d like to push my work upstream.  My local repository now looks like:
image
Unlike the previous workflow, my “master” bookmark moves along, instead of always pointing at the latest pulled commit.  It’s still important that this bookmark sticks around, as we’ll see soon.  Now that I want to push, I want to first pull down incoming commits.  Let’s suppose that someone else also made some commits on another repository and already pushed.  The server repository shows this:
image
Note that we don’t see our bookmarks here, as by default bookmarks don’t get pushed upstream.  When we pull from upstream, we’ll get the commit from the “otherdude” developer.  So, I’ll:
  • hg pull --rebase
Instead a “pull/merge/update” workflow, which generates noisy merge commits, I’ll rebase my three commits against the upstream changes.  Rebase simply replays my three commits against the incoming tip.  That would mean that I expect to see that the parent of “Working on some stuff” to be the “otherdude” commit instead of the “Finishing work on a feature” commit.  After the pull and rebase, my local repository is now:
image
This is what we expected, our commits that originally came after the “Finishing work on a feature” commit got moved AFTER the “otherdude” commit.  This produces a nice clean timeline that makes localizing bugs and merging changes a lot easier.  With a regular pull/merge workflow, you’re merging all 3 commits at once.  With a rebase, I merge one commit at a time, making the potential merges much smaller.  Each merge also modifies each commit, instead of one gigantic merge commit with all changes coming in at once.
Anyway, I’ve pull upstream changes, so now I’m ready to push:
  • hg push –b master
I only want to push that mainline branch, “master”, just like my previous workflows.  By pushing only my “master” branch, I can transfer back and forth between my simplified, mainline workflow and topic branch workflow very easily, with neither conflicting with the other.  In Git, only the current branch is ever pushed by default, but in Hg, it’s the opposite, so I have to a bit more explicit.

Comparing rebase and merge

Just to show what a merge looks like in comparison, let’s say “otherdude” doesn’t rebase before he commits his additional work.  He has some more commits:
image
Now he wants to push these two commits up.  However, the other user already pushed rebased commits, so now the server looks like:
image
Instead of doing a rebase on pull, he does a regular pull and update.  Because other commits have gone in, he’ll need to do a merge:
  • hg pull –u
  • hg merge
  • hg ci –Am “Stupid merge commit”
He tries to pull and update, but since there were commits there, two heads get created and he needs to merge in his changes.  This causes an extra merge AND commit step, and now uglies up the history:
image
So the silly thing about this is the stupid merge commit contains ALL changes from the other two outgoing commits, yet all three commits get pushed!  This also becomes really ugly over time, especially when you have overlapping commits and merges:
image
I’m not sure human beings are meant to comprehend this picture, so I’ll take the rebased workflow with its clean, linear history any day of the week.  With the simplified workflow, rebasing is actually simpler than the pull/merge/commit workflow.  Rebase is good, whether we work in topic branches or not.



source: mercurial-workflows-mainline-workflow

2010年12月15日星期三

Console2+cmd+cygwin replace cmd.exe

Console2


Console is a Windows console window enhancement. Console features include: multiple tabs, text editor-like text selection, different background types, alpha and color-key transparency, configurable font, different window styles


Create new tabs

File -> New tab

Edit -> Setting -> Tabs

Add cmd tab

Title: cmd
Icon: <default>
Shell: C:\WINDOWS\system32\cmd.exe

Add cygwin tab

Title: cygwin
Icon: C:\cygwin\Cygwin.ico
Shell: C:\cygwin\bin\bash.exe --login –i

Save settings to user directory

Customize setting

Console

Shell: C:\WINDOWS\system32\cmd.exe
Appearance
Check:
Use tab titles
Show command
Show command in tabs
Trim tab titles to
Use tab icons

Behavior

Check:
         Copy on select
         Don’t wrap long lines
Clear selection on copy
Trim trailing spaces

Hotkeys

Paste: Ctrl+V

Mouse

Copy/clear selection: None
Select text: Left (uncheck shift)
Paste text: Middle


Add to Right click menu

Open cmd here

Add registry key:
HKEY_CLASSES_ROOT\Directory\shell\Open cmd here\command
Default: C:\Program Files\Console2\Console.exe -t cmd "%1"\

Open cygwin here

Run cygwin setup.exe, install chere package.

Add registry key:
HKEY_CLASSES_ROOT\Directory\shell\Open cygwin\command
C:\Program Files\Console2\Console.exe -t cygwin -r "/bin/xhere /bin/bash.exe '%L'"


Add to Right click context menu 

Create a .reg file, copy and paste below lines and run the .reg file:
 
Windows Registry Editor Version 5.00
 
[HKEY_CLASSES_ROOT\Directory\shell\Open cmd here...]
[HKEY_CLASSES_ROOT\Directory\shell\Open cmd here...\command]
@="\"C:\\Program Files\\Console2\\Console.exe\" -t cmd -r \"/bin/xhere /bin/bash.exe '%L'\""
 
[HKEY_CLASSES_ROOT\Directory\shell\Open Cygwin here...]
[HKEY_CLASSES_ROOT\Directory\shell\Open Cygwin Here...\command]
@="\"C:\\Program Files\\Console2\\Console.exe\" -t cygwin -r \"/bin/xhere /bin/bash.exe '%L'\""