Add a script to "smartly" re-parent a stacked phabricator commit.
Add a script to "smartly" re-parent a stacked phabricator commit.

Summary:
This script changes the current branch to point to a new upstream.
It is morally equivalent to
    git branch -u <new upstream> [old upstream branch-name]
    git p
but uses a technique that -- unlike the above -- is successful
for stacked phabricator diffs.

Here is the situation it is intended to be used:

    git co -b stack1
    ....  # lots of work here
    arc diff

    git co -b stack2     # branched off of stack1!
    ...
    arc diff

    git co stack1
    arc land

    git co stack2
    ???

The `arc land` merges stack1 back into the base branch and deletes
it, leaving stack2 without an upstream.  In a normal world you'd just
do `git branch -u mydeploybranch; git p`, but that doesn't work with
phabricator -- or probably with github -- because phab doesn't just
rebase stack1 onto the base branch, it *squashes* the commits.
(It also rewrites the commit message, so there's a problem even if
stack1 only has one commit in it.)

As a result, at the `???` line stack2 has a bunch of changes it
inherited from stack1, and the base branch has those same changes
but in a totally different commit.  When you try to rebase (by
running `git p`) in stack2, you are liable to get a whole bunch of
conflicts as git tries to reconcile the two versions.

This script fixes that by using a different approach to fix the
upstream.  It works like this:
    git co base_branch
    git co -b stack2.tmp
    git branch -u base_branch     # `co -b` should default to this, but...
    git cherry-pick @{u}..stack2
    git branch -M stack2.tmp stack2
That is, instead of trying to rebase all the changes from stack1
onto stack2, it cherry-picks them on.  The actual implementation is
different due to the fact cherry-pick can be interactive (in case of
conflicts and the like), but that is the general idea.

Test Plan:
I ran this on 5 stacked diffs that I had lying around, each of which
was branched from the same review (so I had stack1 and then stack2a,
stack2b, ... stack2e).  The command ran cleanly on all of them.  One
of them had a merge conflict and I successfully resolved it with `git
cherry-pick --continue`.

This isn't an awesome test though because all of my 5 stack2's were a
single commit, so I wasn't testing multiple cherry-picks very well.

Reviewers: benkraft

Reviewed By: benkraft

Subscribers: #infrastructure

Differential Revision: https://phabricator.khanacademy.org/D45731

Khan/git-workflow,Khan/git-workflow