Phabricator’s and github’s usage of git is very different. With github you are always pushing new commits, but with phabricator you should never push (except when updating a deploy branch from master). You are better off pretending that we don't actually use git, and that the Khan Academy recommended Phabricator workflow is a series of inscrutable magic incantations that must be meticulously performed or you'll release Ẕ̶̨̫̹̌͊͌͑͊̕͢͟a̡̜̦̝͓͇͗̉̆̂͋̏͗̍ͅl̡̛̝͍̅͆̎̊̇̕͜͢ģ̧̧͍͓̜̲͖̹̂͋̆̃̑͗̋͌̊̏ͅǫ̷̧͓̣͚̞̣̋̂̑̊̂̀̿̀̚͟͠ͅ.
If you are still irrationally stubborn, like I am, and really want to continue using the familiar and universal-outside-khan git workflow, then since you will be fighting the Khan tools you need to be firm and unambiguous in communicating to phabricator what you want it to do.
My workflow is always:
- Make a branch.
- Make some changes
- Commit
- Fetch and Rebase against origin master|districts|progreports (this is team specific)
- Git push your branch from your local topic branch to an origin remote topic branch
- This crazy thing:
arc diff --trace --base 'arc:verbose, git:branch-unique(origin/master), arc:prompt' "$(git merge-base origin/master HEAD)"
- Sing "My Way"
After pushing any subsequent commits to any remote branch it automatically closes your phabricator review. You can reopen it in the ui. then you can revise it (pick the phabricator Diff id instead of D67113 below:
arc diff --trace --base 'arc:verbose, git:branch-unique(origin/master), arc:prompt' "$(git merge-base origin/master HEAD)" --update D1234
Pretty much no one in the organization besides me uses this workflow. I prefer the adjective "innovative" rather than "outré" as it avoids having to type the accute accent.
Phabricator | GitHub/GitFlow/Git Branches |
---|---|
Phabricator is based on diffs/patches, not tied to the git history/git tree. This is not inherently better or worse. Or maybe it is? I make no value judgement here. | GitHub/GitFlow is based on branches and commits, intrinsically tied to git history/git tree. This is not inherently better or worse. Or maybe it is? I make no value judgement here. |
You can munge around in your diffs, smash up history, rebase easily, reorder diffs, and pluck out and land top-of-stack diffs. Generally, stacked diffs are a little simpler to manage here, but when things go wrong, they can go very wrong! | You have to be a lot more careful about preserving git history. Generally, stacked diffs can be a bit more annoying, but it’s a lot harder to really break things. You can still do all the things that you can do in Phab, though often it’s required to change history. |
Phabricator is really hard to learn for those coming from the GitHub/GitFlow mindset. It takes a very long time (months, maybe years) to go from “Familiar” to “Proficient”, when also learning the rest of the code base. And, for many, it often isn’t worth the ROI to get to “Mastered”. | GitHub/GitFlow is hard to learn for those coming from the Phabricator mindset. It takes a while, but not nearly as long (a week to a month or two), to get from “Familiar” to “Proficient”. “Mastery” is much more attainable. |
When learning Phabricator, we have lots of really great internal support and documentation to help you. But there are few resources and support in the wider community. | When learning GitHub/GitFlow, we have little internal support and documentation to help you. But there are ample resources and large bodies of support in the wider community. |
Our set up-is very custom to us. Skills here aren’t very transferable to future organizations, and virtually every new employee will need a lot of time to ramp up. | This is the industry standard. Most new employees are already proficient in this type of workflow. Learning it while here will be valuable if and when you leave Khan Academy. |
When you get stuck, it often costs several hours to whole days to get unstuck. Not very many in-house experts; less outside of KA. | When you get stuck, problems are usually very easy to solve through Google or the many available resources. Many in-house experts; many industry experts as well. |
Higher cognitive load around understanding what’s going on. | Lower cognitive load around understanding what’s going on. |
“When learning Phabricator, I totally had imposter syndrome!” | “When learning GitHub, branching, and GitFlow, I totally had imposter syndrome!” |
instead of this common command | phabricator/webapp command |
---|---|
git pull | git p |
git merge | git m |
git checkout | git co |
N/A | git gsu |
N/A | git db, !git deploy-branch |
N/A | git rb, !git review-branch |
GitHub: Pull requests (commits and branches)
Phabricator: Revisions (everything is a diff)
WHY DOES THAT MATTER? For basic usage, it doesn't
Instead of pushing a branch and opening a pull request, you simply run arc diff
$ git checkout -b add-toaster-oven
$ emacs
$ git commit
$ arc diff
- Make your changes
- Create a new commit on top of your previously reviewed change
- Run
arc diff
again - Note the lack of force-pushing
- When a rebase leaves you in a strange state
- When you're working on multiple feature branches
- Use
arc which
to get a sense of your surroundings
$ arc which
If you lose your commit message link and your tree changes
Use the --update revision-id
$ arc diff --update D123
By default, looks at all local changes between your upstream branch (e.g. origin/master) and HEAD
Roughly equivalent to:
$ git diff $(git merge-base origin/master HEAD)..HEAD
This confuses some people
To override, specify a base reference (branch name, SHA, symbolic ref):
$ arc diff <base-ref>
We set a global default, overriding upstream behavior, like this:
$ arc set-config base "git:merge-base(origin/master), arc:prompt"
I'm working off a co-worker's topic branch feature-a, I can send just my changes up for review:
$ git fetch && git checkout feature-a
$ git checkout -b feature-b
$ emacs
$ git commit
$ arc diff feature-a
Only two things you usually want to tweak
- The base, which specifies where your diff begins
- Your differential revision (e.g. D456), which can be manually specified with
$ arc diff --update D456
- Creates or updates a diff between HEAD and your upstream branch
- If you're going to be pushing your branches pre- code-review, I highly recommend overriding your default base
- If it recognizes an existing revision, updates
- Otherwise it creates a new one
- Behavior can be overriden by using
--update D123
or specifying a base-ref
-
By default, you get an email from Phabricator for every action you're a part of, including actions you trigger.
-
To turn this off, go to your email preferences page
--nolint
Skips linting--nounit
Skips unit tests--trace
More verbose--update D62986
pick which diff to update--base 'git:branch-unique(origin/districts)'
pick which the branch as the basis for diffing
Diff against origin/master if it exists, and prompt if it doesn't:
git:merge-base(origin/master), arc:prompt
You can also debug the rulesets by using:
arc:verbose
- By default,
arc diff
will do:git merge-base origin/master HEAD
..HEAD That's a fancy way of saying "all the commits on the current branch that you haven't pushed yet". So, to create a revision in Git, run:
$ nano source_code.c # Make changes.
$ git commit -a # Commit changes.
$ arc diff # Creates a new revision out of ALL unpushed commits on
# this branch.
The git commit step is optional. If there are uncommitted changes in the working copy then Arcanist will ask you to create a commit from them.
Since it uses all the commits on the branch, you can make several commits before sending your changes for review if you prefer.
You can specify a different commit range instead by running:
$ arc diff <commit>
This means to use the range:
git merge-base <commit> HEAD
..HEAD
However, this is a relatively advanced feature. The default is usually correct if you aren't creating branches-on-branches, juggling remotes, etc.
# assume you are on a branch like DIST-1817
git fetch origin districts
git pull --rebase origin districts -s recursive -X theirs
arc diff --trace --base 'arc:verbose, git:branch-unique(origin/districts), arc:prompt' "$(git merge-base origin/master HEAD)"
# Make some local changes
arc diff --trace --base 'arc:verbose, git:branch-unique(origin/districts), arc:prompt' "$(git merge-base origin/master HEAD)" --update D123
git branch --set-upstream-to districts
arc land --onto districts
git push
will close any open phabricator review containing that diff. You then need to reopen it in the ui. Hooray.
export DEPLOY_BRANCH=steve-JIRA-1111
git co D64718 # this calls revisionid-to-diffid.sh in webapp only
# You are now in a detached head state
git switch -c "${DEPLOY_BRANCH}"
git fetch origin master
git pull --rebase origin master -s recursive -X theirs
git push origin "${DEPLOY_BRANCH}" -u
git co master
git p
git co "${DEPLOY_BRANCH}"
git diff master..."${DEPLOY_BRANCH}" #check if changes are as expected