Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2893059
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
63 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/applications/diffusion/editor/DiffusionCommitEditEngine.php b/src/applications/diffusion/editor/DiffusionCommitEditEngine.php
index 3cb0a79657..87c1ba2ed8 100644
--- a/src/applications/diffusion/editor/DiffusionCommitEditEngine.php
+++ b/src/applications/diffusion/editor/DiffusionCommitEditEngine.php
@@ -1,216 +1,217 @@
<?php
final class DiffusionCommitEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'diffusion.commit';
const ACTIONGROUP_AUDIT = 'audit';
const ACTIONGROUP_COMMIT = 'commit';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Commits');
}
public function getSummaryHeader() {
return pht('Edit Commits');
}
public function getSummaryText() {
return pht('Edit commits.');
}
public function getEngineApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
protected function newEditableObject() {
// NOTE: We must return a valid object here so that things like Conduit
// documentation generation work. You can't actually create commits via
// EditEngine. This is enforced with a "No One" creation policy.
$repository = new PhabricatorRepository();
$data = new PhabricatorRepositoryCommitData();
return id(new PhabricatorRepositoryCommit())
->attachRepository($repository)
->attachCommitData($data)
->attachAudits(array());
}
protected function newObjectQuery() {
$viewer = $this->getViewer();
return id(new DiffusionCommitQuery())
->needCommitData(true)
->needAuditRequests(true)
->needAuditAuthority(array($viewer));
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('commit/edit/');
}
protected function newCommentActionGroups() {
return array(
id(new PhabricatorEditEngineCommentActionGroup())
->setKey(self::ACTIONGROUP_AUDIT)
->setLabel(pht('Audit Actions')),
id(new PhabricatorEditEngineCommentActionGroup())
->setKey(self::ACTIONGROUP_COMMIT)
->setLabel(pht('Commit Actions')),
);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Commit');
}
protected function getObjectCreateShortText() {
return pht('Create Commit');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Commit: %s', $object->getDisplayName());
}
protected function getObjectEditShortText($object) {
return $object->getDisplayName();
}
protected function getObjectName() {
return pht('Commit');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return PhabricatorPolicies::POLICY_NOONE;
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$data = $object->getCommitData();
$fields = array();
$fields[] = id(new PhabricatorDatasourceEditField())
->setKey('auditors')
->setLabel(pht('Auditors'))
->setDatasource(new DiffusionAuditorDatasource())
->setUseEdgeTransactions(true)
->setTransactionType(
DiffusionCommitAuditorsTransaction::TRANSACTIONTYPE)
->setCommentActionLabel(pht('Change Auditors'))
->setDescription(pht('Auditors for this commit.'))
->setConduitDescription(pht('Change the auditors for this commit.'))
->setConduitTypeDescription(pht('New auditors.'))
->setValue($object->getAuditorPHIDsForEdit());
$reason = $data->getCommitDetail('autocloseReason', false);
if ($reason !== false) {
switch ($reason) {
case PhabricatorRepository::BECAUSE_REPOSITORY_IMPORTING:
$desc = pht('No, Repository Importing');
break;
case PhabricatorRepository::BECAUSE_AUTOCLOSE_DISABLED:
$desc = pht('No, Repository Publishing Disabled');
break;
case PhabricatorRepository::BECAUSE_NOT_ON_AUTOCLOSE_BRANCH:
$desc = pht('No, Not Reachable from Permanent Ref');
break;
case PhabricatorRepository::BECAUSE_AUTOCLOSE_FORCED:
$desc = pht('Yes, Forced Via bin/repository CLI Tool.');
break;
case null:
$desc = pht('Yes');
break;
default:
$desc = pht('Unknown');
break;
}
- $doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: Autoclose');
+ $doc_href = PhabricatorEnv::getDoclink(
+ 'Diffusion User Guide: Permanent Refs');
$doc_link = phutil_tag(
'a',
array(
'href' => $doc_href,
'target' => '_blank',
),
pht('Learn More'));
$fields[] = id(new PhabricatorStaticEditField())
- ->setLabel(pht('Autoclose?'))
+ ->setLabel(pht('Published?'))
->setValue(array($desc, " \xC2\xB7 ", $doc_link));
}
$actions = DiffusionCommitActionTransaction::loadAllActions();
$actions = msortv($actions, 'getCommitActionOrderVector');
foreach ($actions as $key => $action) {
$fields[] = $action->newEditField($object, $viewer);
}
return $fields;
}
protected function newAutomaticCommentTransactions($object) {
$viewer = $this->getViewer();
$xactions = array();
$inlines = PhabricatorAuditInlineComment::loadDraftComments(
$viewer,
$object->getPHID(),
$raw = true);
$inlines = msort($inlines, 'getID');
$editor = $object->getApplicationTransactionEditor()
->setActor($viewer);
$query_template = id(new DiffusionDiffInlineCommentQuery())
->withCommitPHIDs(array($object->getPHID()));
$xactions = $editor->newAutomaticInlineTransactions(
$object,
$inlines,
PhabricatorAuditActionConstants::INLINE,
$query_template);
return $xactions;
}
protected function newCommentPreviewContent($object, array $xactions) {
$viewer = $this->getViewer();
$type_inline = PhabricatorAuditActionConstants::INLINE;
$inlines = array();
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() === $type_inline) {
$inlines[] = $xaction->getComment();
}
}
$content = array();
if ($inlines) {
$inline_preview = id(new PHUIDiffInlineCommentPreviewListView())
->setViewer($viewer)
->setInlineComments($inlines);
$content[] = phutil_tag(
'div',
array(
'id' => 'inline-comment-preview',
),
$inline_preview);
}
return $content;
}
}
diff --git a/src/applications/diffusion/view/DiffusionBranchListView.php b/src/applications/diffusion/view/DiffusionBranchListView.php
index a2ba34893e..73ad87041a 100644
--- a/src/applications/diffusion/view/DiffusionBranchListView.php
+++ b/src/applications/diffusion/view/DiffusionBranchListView.php
@@ -1,142 +1,141 @@
<?php
final class DiffusionBranchListView extends DiffusionView {
private $branches;
private $commits = array();
public function setBranches(array $branches) {
assert_instances_of($branches, 'DiffusionRepositoryRef');
$this->branches = $branches;
return $this;
}
public function setCommits(array $commits) {
assert_instances_of($commits, 'PhabricatorRepositoryCommit');
$this->commits = mpull($commits, null, 'getCommitIdentifier');
return $this;
}
public function render() {
$drequest = $this->getDiffusionRequest();
$current_branch = $drequest->getBranch();
$repository = $drequest->getRepository();
$commits = $this->commits;
$viewer = $this->getUser();
require_celerity_resource('diffusion-css');
$buildables = $this->loadBuildables($commits);
$have_builds = false;
$can_close_branches = ($repository->isHg());
Javelin::initBehavior('phabricator-tooltips');
- $doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: Autoclose');
$list = id(new PHUIObjectItemListView())
->setFlush(true)
->addClass('diffusion-history-list')
->addClass('diffusion-branch-list');
foreach ($this->branches as $branch) {
$build_view = null;
$button_bar = new PHUIButtonBarView();
$commit = idx($commits, $branch->getCommitIdentifier());
if ($commit) {
$details = $commit->getSummary();
$datetime = phabricator_datetime($commit->getEpoch(), $viewer);
$buildable = idx($buildables, $commit->getPHID());
if ($buildable) {
$build_view = $this->renderBuildable($buildable, 'button');
}
} else {
$datetime = null;
$details = null;
}
if ($repository->supportsBranchComparison()) {
$compare_uri = $drequest->generateURI(
array(
'action' => 'compare',
'head' => $branch->getShortName(),
));
$can_compare = ($branch->getShortName() != $current_branch);
if ($can_compare) {
$button_bar->addButton(
id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-balance-scale')
->setToolTip(pht('Compare'))
->setButtonType(PHUIButtonView::BUTTONTYPE_SIMPLE)
->setWorkflow(true)
->setHref($compare_uri));
}
}
$browse_href = $drequest->generateURI(
array(
'action' => 'browse',
'branch' => $branch->getShortName(),
));
$button_bar->addButton(
id(new PHUIButtonView())
->setIcon('fa-code')
->setHref($browse_href)
->setTag('a')
->setTooltip(pht('Browse'))
->setButtonType(PHUIButtonView::BUTTONTYPE_SIMPLE));
$commit_link = $repository->getCommitURI(
$branch->getCommitIdentifier());
$commit_name = $repository->formatCommitName(
$branch->getCommitIdentifier(), $local = true);
$commit_tag = id(new PHUITagView())
->setName($commit_name)
->setHref($commit_link)
->setType(PHUITagView::TYPE_SHADE)
->setColor(PHUITagView::COLOR_INDIGO)
->setBorder(PHUITagView::BORDER_NONE)
->setSlimShady(true);
$subhead = array($commit_tag, ' ', $details);
$item = id(new PHUIObjectItemView())
->setHeader($branch->getShortName())
->setHref($drequest->generateURI(
array(
'action' => 'history',
'branch' => $branch->getShortName(),
)))
->setSubhead($subhead)
->setSideColumn(array(
$build_view,
$button_bar,
));
if ($branch->getShortName() == $repository->getDefaultBranch()) {
$item->setStatusIcon('fa-code-fork', pht('Default Branch'));
}
$item->addAttribute(array($datetime));
if ($can_close_branches) {
$fields = $branch->getRawFields();
$closed = idx($fields, 'closed');
if ($closed) {
$status = pht('Branch Closed');
$item->setDisabled(true);
} else {
$status = pht('Branch Open');
}
$item->addAttribute($status);
}
$list->addItem($item);
}
return $list;
}
}
diff --git a/src/applications/diffusion/view/DiffusionBranchTableView.php b/src/applications/diffusion/view/DiffusionBranchTableView.php
index bd539e0a25..3e84075a51 100644
--- a/src/applications/diffusion/view/DiffusionBranchTableView.php
+++ b/src/applications/diffusion/view/DiffusionBranchTableView.php
@@ -1,165 +1,166 @@
<?php
final class DiffusionBranchTableView extends DiffusionView {
private $branches;
private $commits = array();
public function setBranches(array $branches) {
assert_instances_of($branches, 'DiffusionRepositoryRef');
$this->branches = $branches;
return $this;
}
public function setCommits(array $commits) {
assert_instances_of($commits, 'PhabricatorRepositoryCommit');
$this->commits = mpull($commits, null, 'getCommitIdentifier');
return $this;
}
public function render() {
$drequest = $this->getDiffusionRequest();
$current_branch = $drequest->getBranch();
$repository = $drequest->getRepository();
$commits = $this->commits;
$viewer = $this->getUser();
$buildables = $this->loadBuildables($commits);
$have_builds = false;
$can_close_branches = ($repository->isHg());
Javelin::initBehavior('phabricator-tooltips');
- $doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: Autoclose');
+ $doc_href = PhabricatorEnv::getDoclink(
+ 'Diffusion User Guide: Permanent Refs');
$rows = array();
$rowc = array();
foreach ($this->branches as $branch) {
$commit = idx($commits, $branch->getCommitIdentifier());
if ($commit) {
$details = $commit->getSummary();
$datetime = $viewer->formatShortDateTime($commit->getEpoch());
$buildable = idx($buildables, $commit->getPHID());
if ($buildable) {
$build_status = $this->renderBuildable($buildable);
$have_builds = true;
} else {
$build_status = null;
}
} else {
$datetime = null;
$details = null;
$build_status = null;
}
switch ($repository->shouldSkipAutocloseBranch($branch->getShortName())) {
case PhabricatorRepository::BECAUSE_REPOSITORY_IMPORTING:
$icon = 'fa-times bluegrey';
$tip = pht('Repository Importing');
break;
case PhabricatorRepository::BECAUSE_AUTOCLOSE_DISABLED:
$icon = 'fa-times bluegrey';
$tip = pht('Repository Publishing Disabled');
break;
case PhabricatorRepository::BECAUSE_BRANCH_UNTRACKED:
$icon = 'fa-times bluegrey';
$tip = pht('Branch Untracked');
break;
case PhabricatorRepository::BECAUSE_BRANCH_NOT_AUTOCLOSE:
$icon = 'fa-times bluegrey';
$tip = pht('Branch Not Permanent');
break;
case null:
$icon = 'fa-check bluegrey';
$tip = pht('Permanent Branch');
break;
default:
$icon = 'fa-question';
$tip = pht('Status Unknown');
break;
}
$status_icon = id(new PHUIIconView())
->setIcon($icon)
->addSigil('has-tooltip')
->setHref($doc_href)
->setMetadata(
array(
'tip' => $tip,
'size' => 200,
));
$fields = $branch->getRawFields();
$closed = idx($fields, 'closed');
if ($closed) {
$status = pht('Closed');
} else {
$status = pht('Open');
}
$rows[] = array(
$this->linkBranchHistory($branch->getShortName()),
phutil_tag(
'a',
array(
'href' => $drequest->generateURI(
array(
'action' => 'browse',
'branch' => $branch->getShortName(),
)),
),
$branch->getShortName()),
self::linkCommit(
$drequest->getRepository(),
$branch->getCommitIdentifier()),
$build_status,
$status,
AphrontTableView::renderSingleDisplayLine($details),
$status_icon,
$datetime,
);
if ($branch->getShortName() == $current_branch) {
$rowc[] = 'highlighted';
} else {
$rowc[] = null;
}
}
$view = new AphrontTableView($rows);
$view->setHeaders(
array(
null,
pht('Branch'),
pht('Head'),
null,
pht('State'),
pht('Details'),
null,
pht('Committed'),
));
$view->setColumnClasses(
array(
'',
'pri',
'',
'icon',
'',
'wide',
'',
'right',
));
$view->setColumnVisibility(
array(
true,
true,
true,
$have_builds,
$can_close_branches,
));
$view->setRowClasses($rowc);
return $view->render();
}
}
diff --git a/src/docs/user/field/repository_imports.diviner b/src/docs/user/field/repository_imports.diviner
index 1b1c92bbc0..262874186c 100644
--- a/src/docs/user/field/repository_imports.diviner
+++ b/src/docs/user/field/repository_imports.diviner
@@ -1,247 +1,247 @@
@title Troubleshooting Repository Imports
@group fieldmanual
Guide to the troubleshooting repositories which import incompletely.
Overview
========
When you first import an external source code repository (or push new commits to
a hosted repository), Phabricator imports those commits in the background.
While a repository is initially importing, some features won't work. While
individual commits are importing, some of their metadata won't be available in
the web UI.
Sometimes, the import process may hang or fail to complete. This document can
help you understand the import process and troubleshoot problems with it.
Understanding the Import Pipeline
=================================
Phabricator first performs commit discovery on repositories. This examines
a repository and identifies all the commits in it at a very shallow level,
then creates stub objects for them. These stub objects primarily serve to
assign various internal IDs to each commit.
Commit discovery occurs in the update phase, and you can learn more about
updates in @{article:Diffusion User Guide: Repository Updates}.
After commits are discovered, background tasks are queued to actually import
commits. These tasks do things like look at commit messages, trigger mentions
-and autoclose rules, cache changes, trigger Herald, publish feed stories and
-email, and apply Owners rules. You can learn more about some of these steps in
-@{article:Diffusion User Guide: Autoclose}.
+and update related objects, cache changes, trigger Herald, publish feed stories
+and email, and apply Owners rules. You can learn more about some of these steps
+in @{article:Diffusion User Guide: Permanent Refs}.
Specifically, the import pipeline has four steps:
- **Message**: Parses the commit message and author metadata.
- **Change**: Caches the paths the commit affected.
- **Owners**: Runs Owners rules.
- **Herald**: Runs Herald rules and publishes notifications.
These steps run in sequence for each commit, but all discovered commits import
in parallel.
Identifying Missing Steps
=========================
There are a few major pieces of information you can look at to understand where
the import process is stuck.
First, to identify which commits have missing import steps, run this command:
```
phabricator/ $ ./bin/repository importing rXYZ
```
That will show what work remains to be done. Each line shows a commit which
is discovered but not imported, and the import steps that are remaining for
that commit. Generally, the commit is stuck on the first step in the list.
Second, load the Daemon Console (at `/daemon/` in the web UI). This will show
what work is currently being done and waiting to complete. The most important
sections are "Queued Tasks" (work waiting in queue) and "Leased Tasks"
(work currently being done).
Third, run this command to look at the daemon logs:
```
phabricator/ $ ./bin/phd log
```
This can show you any errors the daemons have encountered recently.
The next sections will walk through how to use this information to understand
and resolve the issue.
Handling Permanent Failures
===========================
Some commits can not be imported, which will permanently stop a repository from
fully importing. These are rare, but can be caused by unusual data in a
repository, version peculiarities, or bugs in the importer.
Permanent failures usually look like a small number of commits stuck on the
"Message" or "Change" steps in the output of `repository importing`. If you
have a larger number of commits, it is less likely that there are any permanent
problems.
In the Daemon console, permanent failures usually look like a small number of
tasks in "Leased Tasks" with a large failure count. These tasks are retrying
until they succeed, but a bug is permanently preventing them from succeeding,
so they'll rack up a large number of retries over time.
In the daemon log, these commits usually emit specific errors showing why
they're failing to import.
These failures are the easiest to identify and understand, and can often be
resolved quickly. Choose some failing commit from the output of `bin/repository
importing` and use this command to re-run any missing steps manually in the
foreground:
```
phabricator/ $ ./bin/repository reparse --importing --trace rXYZabcdef012...
```
This command is always safe to run, no matter what the actual root cause of
the problem is.
If this fails with an error, you've likely identified a problem with
Phabricator. Collect as much information as you can about what makes the commit
special and file a bug in the upstream by following the instructions in
@{article:Contributing Bug Reports}.
If the commit imports cleanly, this is more likely to be caused by some other
issue.
Handling Temporary Failures
===========================
Some commits may temporarily fail to import: perhaps the network or services
may have briefly been down, or some configuration wasn't quite right, or the
daemons were killed halfway through the work.
These commits will retry eventually and usually succeed, but some of the retry
time limits are very conservative (up to 24 hours) and you might not want to
wait that long.
In the Daemon console, temporarily failures usually look like tasks in the
"Leased Tasks" column with a large "Expires" value but a low "Failures" count
(usually 0 or 1). The "Expires" column is showing how long Phabricator is
waiting to retry these tasks.
In the daemon log, these temporary failures might have created log entries, but
might also not have. For example, if the failure was rooted in a network issue
that probably will create a log entry, but if the failure was rooted in the
daemons being abruptly killed that may not create a log entry.
You can follow the instructions from "Handling Permanent Failures" above to
reparse steps individually to look for an error that represents a root cause,
but sometimes this can happen because of some transient issue which won't be
identifiable.
The easiest way to fix this is to restart the daemons. When you restart
daemons, all task leases are immediately expired, so any tasks waiting for a
long time will run right away:
```
phabricator/ $ ./bin/phd restart
```
This command is always safe to run, no matter what the actual root cause of
the problem is.
After restarting the daemons, any pending tasks should be able to retry
immediately.
For more information on managing the daemons, see
@{article:Managing Daemons with phd}.
Forced Parsing
==============
In rare cases, the actual tasks may be lost from the task queue. Usually, they
have been stolen by gremlins or spirited away by ghosts, or someone may have
been too ambitious with running manual SQL commands and deleted a bunch of
extra things they shouldn't have.
There is no normal set of conditions under which this should occur, but you can
force Phabricator to re-queue the tasks to recover from it if it does occur.
This will look like missing steps in `repository importing`, but nothing in the
"Queued Tasks" or "Leased Tasks" sections of the daemon console. The daemon
logs will also be empty, since the tasks have vanished.
To re-queue parse tasks for a repository, run this command, which will queue
up all of the missing work in `repository importing`:
```
phabricator/ $ ./bin/repository reparse --importing --all rXYZ
```
This command may cause duplicate work to occur if you have misdiagnosed the
problem and the tasks aren't actually lost. For example, it could queue a
second task to perform publishing, which could cause Phabricator to send a
second copy of email about the commit. Other than that, it is safe to run even
if this isn't the problem.
After running this command, you should see tasks in "Queued Tasks" and "Leased
Tasks" in the console which correspond to the commits in `repository
importing`, and progress should resume.
Forced Imports
==============
In some cases, you might want to force a repository to be flagged as imported
even though the import isn't complete. The most common and reasonable case
where you might want to do this is if you've identified a permanent failure
with a small number of commits (maybe just one) and reported it upstream, and
are waiting for a fix. You might want to start using the repository immediately,
even if a few things can't import yet.
You should be cautious about doing this. The "importing" flag controls
publishing of notifications and email, so if you flag a repository as imported
but it still has a lot of work queued, it may send an enormous amount of email
as that work completes.
To mark a repository as imported even though it really isn't, run this
command:
```
phabricator/ $ ./bin/repository mark-imported rXYZ
```
If you do this by mistake, you can reverse it later by using the
`--mark-not-imported` flag.
General Tips
============
Broadly, `bin/repository` contains several useful debugging commands which
let you figure out where failures are occurring. You can add the `--trace` flag
to any command to get more details about what it is doing. For any command,
you can use `help` to learn more about what it does and which flag it takes:
```
phabricator/ $ bin/repository help <command>
```
In particular, you can use flags with the `repository reparse` command to
manually run parse steps in the foreground, including re-running steps and
running steps out of order.
Next Steps
==========
Continue by:
- returning to the @{article:Diffusion User Guide}.
diff --git a/src/docs/user/userguide/arcanist_diff.diviner b/src/docs/user/userguide/arcanist_diff.diviner
index 3480070b5f..4140deb537 100644
--- a/src/docs/user/userguide/arcanist_diff.diviner
+++ b/src/docs/user/userguide/arcanist_diff.diviner
@@ -1,209 +1,208 @@
@title Arcanist User Guide: arc diff
@group userguide
Guide to running `arc diff`, to send changes to Differential for review.
This article assumes you have `arc` installed and running; if not, see
@{article:Arcanist User Guide} for help getting it set up.
Before running `arc diff`, you should create a `.arcconfig` file. If someone
set things up for you, they may already have done this. See
@{article:Arcanist User Guide: Configuring a New Project} for instructions and
information.
= Overview =
While `arc` has a large number of commands that interface with various
Phabricator applications, the primary use of `arc` is to send changes for
review in Differential (for more information on Differential, see
@{article:Differential User Guide}). If you aren't familiar with Differential,
it may be instructive to read that article first to understand the big picture
of how the code review workflow works.
You send changes for review by running `arc diff`. The rest of this document
explains how to use `arc diff`, and how the entire review workflow operates for
different version control systems.
= Subversion =
In Subversion, `arc diff` sends the **uncommitted changes in the working copy**
for review.
To **create a revision** in SVN:
$ nano source_code.c # Make changes.
$ arc diff
This will prompt you for information about the revision. To later **update an
existing revision**, just do the same thing:
$ nano source_code.c # Make more changes.
$ arc diff
This time, `arc` will prompt you to update the revision. Once your revision has
been accepted, you can commit it like this:
$ arc commit
= Git =
In Git, `arc diff` sends **all commits in a range** for review. By default,
this range is:
`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.
To **update a revision**, just do the same thing:
$ nano source_code.c # Make more changes.
$ git commit -a # Commit them.
$ arc diff # This prompts you to update revision information.
The `git commit` step is optional. If there are uncommitted changes in the
working copy then Arcanist will ask you to amend them to the commit.
When your revision has been accepted, you can usually push it like this:
$ arc land <branch> # Merges <branch> into master and pushes.
`arc land` makes some assumptions about your workflow which might not be
true. Consult the documentation before you use it. You should also look at
`arc amend`, which may fit your workflow better.
= Mercurial =
In Mercurial, `arc diff` sends **all commits in a range** for review. By
default, this range is changes between the first non-outgoing parent of any
revision in history and the directory state. This is a fancy way of saying
"every outgoing change since the last merge". It includes any uncommitted
changes in the working copy, although you will be prompted to include these.
To **create a revision** in Mercurial, run:
$ nano source_code.c # Make changes.
$ hg commit # Commit changes.
$ arc diff # Creates a new revision out of ALL outgoing commits
# on this branch since the last merge.
The `hg 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 outgoing 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 from that commit to the directory state. However,
this is an advanced feature and the default is usually correct.
To **update a revision**, just do the same thing:
$ nano source_code.c # Make changes.
$ hg commit # Commit changes.
$ arc diff # This prompts you to update revision information.
The `hg commit` step is optional. If there are uncommitted changes in the
working copy then Arcanist will ask you to create a commit from them (or amend
them to the previous commit if supported).
When your revision has been accepted, push it normally. (`arc` does not have
push integration in Mercurial because it can't force merges and thus can't
guarantee it will be able to do anything useful.)
= Pushing and Closing Revisions =
After changes have been accepted, you generally push them and close the
revision. `arc` has several workflows which help with this, by:
- squashing or merging changes from a feature branch into a master branch
(if relevant);
- formatting a good commit message with all the information from Differential;
and
- automatically closing the revision.
You don't need to use any of these workflows: you can just run `git push`,
`hg push` or `svn commit` and then manually close the revision from the web.
However, these workflows can make common development strategies more convenient,
and give you better commit messages in the repository. The workflows `arc`
supports are:
- `arc land`: Works in Git if you develop in feature branches. Does a merge
or squash-merge from your feature branch into some master branch, provides
a detailed commit message, pushes master, and then deletes your branch.
- `arc amend`: Works in Git if you can't use `arc land`. Amends HEAD with
a detailed commit message.
- `arc commit`: Works in Subversion. Runs `svn commit` with a detailed commit
message.
- `arc close-revision`: Works anywhere, closes a revision from the CLI
without going through the web UI.
You can use `arc help <command>` for detailed help with any of these.
Differential will make a guess about a next step on accepted revisions, but it
may not be the best next step for your workflow.
-Phabricator will also automatically close revisions, if the changes are pushed
+Phabricator will also automatically close revisions if the changes are pushed
to a repository that is tracked in Diffusion. Specifically, it will close
revisions based on commit and tree hashes, and `Differential Revision`
-identifiers in commit messages. (You can disable this feature by disabling
-"Autoclose" in the Repository configuration.)
+identifiers in commit messages.
If you push to an untracked repository (or `arc` can't figure out that it's
tracked), `arc land`, `arc amend` and `arc commit` will implicitly run
`arc close-revision`.
= General Information =
This information is not unique to a specific version control system.
== Force Diff Only ==
You can create just a diff (rather than a revision) with `--preview` (or
`--only`, but this disables other features). You can later use it to create
or update a revision from the web UI.
== Other Diff Sources ==
You can create a diff out of an arbitrary patch file by using `--raw` and piping
it to stdin. In most cases this will only create a diff, not a revision. You
can use the web UI to create a revision from the diff, or update an existing
revision.
== Force Create / Update ==
`arc` uses information about the working copy (like the path, branch name, local
commit hashes, and local tree hashes, depending on which version control system
you are using) to figure out whether you intend to create or update a revision.
If it guesses incorrectly, you can force it to either create or update a
revision with:
$ arc diff --create # Force "create".
$ arc diff --update <revision> # Force "update".
You can figure out what `arc` believes to be in the working copy with
`arc which`.
diff --git a/src/docs/user/userguide/diffusion.diviner b/src/docs/user/userguide/diffusion.diviner
index 7c48d7a636..8ee66d3f8f 100644
--- a/src/docs/user/userguide/diffusion.diviner
+++ b/src/docs/user/userguide/diffusion.diviner
@@ -1,94 +1,94 @@
@title Diffusion User Guide
@group userguide
Guide to Diffusion, the Phabricator application for hosting and browsing
repositories.
Overview
========
Diffusion allows you to create repositories so that you can browse them from
the web and interact with them from other applications.
Diffusion can host repositories locally, or observe existing remote
repositories which are hosted elsewhere (for example, on GitHub, Bitbucket, or
other existing hosting). Both types of repositories can be browsed and
interacted with, but hosted repositories support some additional triggers
and access controls which are not available for observed repositories.
Diffusion is integrated with the other tools in the Phabricator suite. For
instance:
- when you commit Differential revisions to a tracked repository, they are
automatically updated and linked to the corresponding commits;
- you can add Herald rules to notify you about commits that match certain
rules;
- for hosted repositories, Herald can enforce granular access control rules;
- in all the tools, commit names are automatically linked.
The remainder of this document walks through creating, configuring, and
managing repositories.
Adding Repositories
===================
Repository administration is accomplished through Diffusion. You can use the
web interface in Diffusion to observe an external repository or create a new
hosted repository.
- For hosted repositories, make sure you go through the setup instructions
in @{article:Diffusion User Guide: Repository Hosting} first.
- For all repositories, you'll need to be running the daemons. If you have
not set them up yet, see @{article:Managing Daemons with phd}.
By default, you must be an administrator to create a new repository. You can
change this in the application settings.
Managing Repositories
=====================
Diffusion repositories have an array of configurable options and behaviors. For
details on the available options and guidance on managing and administrating
repositories, see @{article:Diffusion User Guide: Managing Repositories}.
Repositories can also be managed via the API. For an overview on using the
API to create and edit repositories, see
@{article:Diffusion User Guide: Repositories API}.
Repository Clustering
=====================
Phabricator repository hosts can be set up in a cluster configuration so you
can lose hosts with minimal downtime and data loss. This is an advanced feature
which most installs do not need to pursue.
To get started with clustering, see @{article:Clustering Introduction}. For
details on repository clustering, see @{article:Cluster: Repositories}.
Next Steps
==========
Continue by:
- learning how to creating a symbol index at
@{article:Diffusion User Guide: Symbol Indexes}; or
- setting up repository hosting with
@{article:Diffusion User Guide: Repository Hosting}; or
- managing repository hooks with
@{article:Diffusion User Guide: Commit Hooks}; or
- understanding daemons in more detail with
@{article:Managing Daemons with phd}.
If you're having trouble getting things working, these topic guides may be
helpful:
- - get details about automatically closing tasks and revisions in response
- to commits in @{article:Diffusion User Guide: Autoclose}; or
+ - get details about automatically taking actions in response to commits in
+ @{article:Diffusion User Guide: Permanent Refs}; or
- understand how Phabricator updates repositories with
@{article:Diffusion User Guide: Repository Updates}; or
- fix issues with repository imports with
@{article:Troubleshooting Repository Imports}.
diff --git a/src/docs/user/userguide/diffusion_autoclose.diviner b/src/docs/user/userguide/diffusion_autoclose.diviner
deleted file mode 100644
index 796a3b0404..0000000000
--- a/src/docs/user/userguide/diffusion_autoclose.diviner
+++ /dev/null
@@ -1,84 +0,0 @@
-@title Diffusion User Guide: Autoclose
-@group userguide
-
-Explains when Diffusion will close tasks and revisions upon discovery of related
-commits.
-
-Overview
-========
-
-Diffusion can close tasks and revisions when related commits appear in a
-repository. For example, if you make a commit with `Fixes T123` in the commit
-message, Diffusion will close the task `T123`.
-
-This document explains how autoclose works, how to configure it, and how to
-troubleshoot it.
-
-Troubleshooting Autoclose
-=========================
-
-You can check if a branch is currently configured to autoclose on the
-management page for the given repository under the branches menu item.
-You should see one of these statuses next to the name of the branch:
-
- - **Autoclose On** Autoclose is active for this branch.
- - **Repository Importing** This repository is still importing.
- Autoclose does not activate until a repository finishes importing for the
- first time. This prevents situations where you import a repository and
- accidentally close hundreds of related objects during import. Autoclose
- will activate for new commits after the initial import completes.
- - **Tracking Off** This branch is not tracked. Because it
- is not tracked, commits on it won't be seen and won't be discovered.
- - **Autoclose Off** Autoclose is not enabled for
- this branch. You can adjust which branches autoclose in **Edit Repository**.
- This option is only available in Git.
-
-If a branch is in good shape, you can check a specific commit by viewing it
-in the web UI and clicking **Edit Commit**. There should be an **Autoclose?**
-field visible in the form, with possible values listed below.
-
-Note that this field records the state of the world at the time the commit was
-processed, and does not necessarily reflect the current state of the world.
-For example, if a commit did not trigger autoclose because it was processed
-during initial import, the field will still show **No, Repository Importing**
-even after import completes. This means that the commit did not trigger
-autoclose because the repository was importing at the time it was processed,
-not necessarily that the repository is still importing.
-
- - **Yes** At the time the commit was imported, autoclose triggered and
- Phabricator attempted to close related objects.
- - **No, Repository Importing** At the time the commit was processed, the
- repository was still importing. Autoclose does not activate until a
- repository fully imports for the first time.
- - **No, Autoclose Disabled** At the time the commit was processed, the
- repository had autoclose disabled.
- - **No, Not On Autoclose Branch** At the time the commit was processed,
- no containing branch was configured to autoclose.
- - //Field Not Present// This commit was processed before we implemented
- this diagnostic feature, and no information is available.
-
-
-Manually Closing Revisions
-==========================
-
-If autoclose didn't activate for some reason and you want to manually close
-revisions, you can do so in several ways:
-
-**Close Revision**: The revision author can use the "Close Revision" action
-from the web UI, located in the action dropdown on the revision page (where
-reviewers would "Accept Revision" or "Request Changes").
-
-`differential.always-allow-close`: If you set this option in {nav Config},
-any user can take the "Close Revision" action in the web UI.
-
-`arc close-revision`: You can close revisions from the command line by using
-`arc close-revision`.
-
-
-Next Steps
-==========
-
-Continue by:
-
- - troubleshooting in greater depth with
- @{article:Troubleshooting Repository Imports}.
diff --git a/src/docs/user/userguide/diffusion_managing.diviner b/src/docs/user/userguide/diffusion_managing.diviner
index a671b0f09e..aa52c1c475 100644
--- a/src/docs/user/userguide/diffusion_managing.diviner
+++ b/src/docs/user/userguide/diffusion_managing.diviner
@@ -1,427 +1,452 @@
@title Diffusion User Guide: Managing Repositories
@group userguide
Guide to configuring and managing repositories in Diffusion.
Overview
========
After you create a new repository in Diffusion or select **Manage Repository**
from the main screen if an existing repository, you'll be taken to the
repository management interface for that repository.
On this interface, you'll find many options which allow you to configure the
behavior of a repository. This document walks through the options.
Basics
======
The **Basics** section of the management interface allows you to configure
the repository name, description, and identifiers. You can also activate or
deactivate the repository here, and configure a few other miscellaneous
settings.
Basics: Name
============
The repository name is a human-readable primary name for the repository. It
does not need to be unique
Because the name is not unique and does not have any meaningful restrictions,
it's fairly ambiguous and isn't very useful as an identifier. The other basic
information (primarily callsigns and short names) gives you control over
repository identifiers.
Basics: Callsigns
=================
Each repository can optionally be identified by a "callsign", which is a short
uppercase string like "P" (for Phabricator) or "ARC" (for Arcanist).
The primary goal of callsigns is to namespace commits to SVN repositories: if
you use multiple SVN repositories, each repository has a revision 1, revision 2,
etc., so referring to them by number alone is ambiguous.
However, even for Git and Mercurial they impart additional information to human
readers and allow parsers to detect that something is a commit name with high
probability (and allow distinguishing between multiple copies of a repository).
Configuring a callsign can make interacting with a commonly-used repository
easier, but you may not want to bother assigning one to every repository if you
have some similar, templated, or rarely-used repositories.
If you choose to assign a callsign to a repository, it must be unique within an
install but do not need to be globally unique, so you are free to use the
single-letter callsigns for brevity. For example, Facebook uses "E" for the
Engineering repository, "O" for the Ops repository, "Y" for a Yum package
repository, and so on, while Phabricator uses "P", "ARC", "PHU" for libphutil,
and "J" for Javelin. Keeping callsigns brief will make them easier to use, and
the use of one-character callsigns is encouraged if they are reasonably
evocative.
If you configure a callsign like `XYZ`, Phabricator will activate callsign URIs
and activate the callsign identifier (like `rXYZ`) for the repository. These
more human-readable identifiers can make things a little easier to interact
with.
Basics: Short Name
==================
Each repository can optionally have a unique short name. Short names must be
unique and have some minor restrictions to make sure they are unambiguous and
appropriate for use as directory names and in URIs.
Basics: Description
===================
You may optionally provide a brief (or, at your discretion, excruciatingly
long) human-readable description of the repository. This description will be
shown on the main repository page.
You can also create a `README` file at the repository root (or in any
subdirectory) to provide information about the repository. These formats are
supported:
| File Name | Rendered As...
|-------------------|---------------
| `README` | Plain Text
| `README.txt` | Plain Text
| `README.remarkup` | Remarkup
| `README.md` | Remarkup
| `README.rainbow` | Rainbow
Basics: Encoding
================
Before content from the repository can be shown in the web UI or embedded in
other contexts like email, it must be converted to UTF-8.
Most source code is written in UTF-8 or a subset of UTF-8 (like plain ASCII)
already, so everything will work fine. The majority of repositories do not need
to adjust this setting.
If your repository is primarily written in some other encoding, specify it here
so Phabricator can convert from it properly when reading content to embed in
a webpage or email.
Basics: Dangerous Changes
=========================
By default, repositories are protected against dangerous changes. Dangerous
changes are operations which rewrite or destroy repository history (for
example, by deleting or rewriting branches). Normally, these take the form
of `git push --force` or similar.
It is normally a good idea to leave this protection enabled because most
scalable workflows rarely rewrite repository history and it's easy to make
mistakes which are expensive to correct if this protection is disabled.
If you do occasionally need to rewrite published history, you can treat this
option like a safety: disable it, perform required rewrites, then enable it
again.
If you fully disable this at the repository level, you can still use Herald to
selectively protect certain branches or grant this power to a limited set of
users.
This option is only available in Git and Mercurial, because it is impossible
to make dangerous changes in Subversion.
This option has no effect if a repository is not hosted because Phabricator
can not prevent dangerous changes in a remote repository it is merely
observing.
+Basics: Disable Publishing
+==========================
+
+You can disable publishing for a repository. For more details on what this
+means, see @{article:Diffusion User Guide: Permanent Refs}.
+
+This is primarily useful if you need to perform major maintenance on a
+repository (like rewriting a large part of the repository history) and you
+don't want the maintenance to generate a large volume of email and
+notifications. You can disable publishing, apply major changes, wait for the
+new changes to import, and then reactivate publishing.
+
+
Basics: Deactivate Repository
=============================
Repositories can be deactivated. Deactivating a repository has these effects:
- the repository will no longer be updated;
- users will no longer be able to clone/fetch/checkout the repository;
- users will no longer be able to push to the repository; and
- the repository will be hidden from view in default queries.
When repositories are created for the first time, they are deactivated. This
gives you an opportunity to customize settings, like adjusting policies or
configuring a URI to observe. You must activate a repository before it will
start working normally.
Basics: Delete Repository
=========================
Repositories can not be deleted from the web UI, so this option is always
disabled. Clicking it gives you information about how to delete a repository.
Repositories can only be deleted from the command line, with `bin/remove`:
```
$ ./bin/remove destroy <repository>
```
WARNING: This command will issue you a dire warning about the severity of the
action you are taking. Heed this warning. You are **strongly discouraged** from
destroying repositories. Instead, deactivate them.
Policies
========
The **Policies** section of the management interface allows you to review and
manage repository access policies.
You can configure granular access policies for each repository to control who
can view, clone, administrate, and push to the repository.
Policies: View
==============
The view policy for a repository controls who can view the repository from
the web UI and clone, fetch, or check it out from Phabricator.
Users who can view a repository can also access the "Manage" interface to
review information about the repository and examine the edit history, but can
not make any changes.
Policies: Edit
==============
The edit policy for a repository controls who can change repository settings
using the "Manage" interface. In essence, this is permission to administrate
the repository.
You must be able to view a repository to edit it.
You do not need this permission to push changes to a repository.
Policies: Push
==============
The push policy for a repository controls who can push changes to the
repository.
This policy has no effect if Phabricator is not hosting the repository, because
it can not control who is allowed to make changes to a remote repository it is
merely observing.
You must also be able to view a repository to push to it.
You do not need to be able to edit a repository to push to it.
Further restrictions on who can push (and what they can push) can be configured
for hosted repositories with Herald, which allows you to write more
sophisticated rules that evaluate when Phabricator receives a push. To get
started with Herald, see @{article:Herald User Guide}.
Additionally, Git and Mercurial repositories have a setting which allows
you to **Prevent Dangerous Changes**. This setting is enabled by default and
will prevent any users from pushing changes which rewrite or destroy history.
URIs
====
The **URIs** panel allows you to add and manage URIs which Phabricator will
fetch from, serve from, and push to.
These options are covered in detail in @{article:Diffusion User Guide: URIs}.
Limits
======
The **Limits** panel allows you to configure limits and timeouts.
**Filesize Limit**: Allows you to set a maximum filesize for any file in the
repository. If a commit creates a larger file (or modifies an existing file so
it becomes too large) it will be rejected. This option only applies to hosted
repositories.
This limit is primarily intended to make it more difficult to accidentally push
very large files that shouldn't be version controlled (like logs, binaries,
machine learning data, or media assets). Pushing huge datafiles by mistake can
make the repository unwieldy by dramatically increasing how much data must be
transferred over the network to clone it, and simply reverting the changes
doesn't reduce the impact of this kind of mistake.
**Clone/Fetch Timeout**: Configure the internal timeout for creating copies
of this repository during operations like intracluster synchronization and
Drydock working copy construction. This timeout does not affect external
users.
**Touch Limit**: Apply a limit to the maximum number of paths that any commit
may touch. If a commit affects more paths than this limit, it will be rejected.
This option only applies to hosted repositories. Users may work around this
limit by breaking the commit into several smaller commits which each affect
fewer paths.
This limit is intended to offer a guard rail against users making silly
mistakes that create obviously mistaken changes, like copying an entire
repository into itself and pushing the result. This kind of change can take
some effort to clean up if it becomes part of repository history.
Note that if you move a file, both the old and new locations count as touched
paths. You should generally configure this limit to be more than twice the
number of files you anticipate any user ever legitimately wanting to move in
a single commit. For example, a limit of `20000` will let users move up to
10,000 files in a single commit, but will reject users mistakenly trying to
push a copy of another repository or a directory with a million logfiles or
whatever other kind of creative nonsense they manage to dream up.
Branches
========
The **Branches** panel allows you to configure how Phabricator interacts with
branches.
This panel is not available for Subversion repositories, because Subversion
does not have formal branches.
-You can configure **Default Branch**. This controls which branch is shown by
+You can configure a **Default Branch**. This controls which branch is shown by
default in the UI. If no branch is provided, Phabricator will use `master` in
Git and `default` in Mercurial.
-If you want Diffusion to ignore some branches in the repository, you can
-configure **Track Only**. Other branches will be ignored. If you do not specify
-any branches, all branches are tracked.
+**Fetch Refs**: In Git, if you are observing a remote repository, you can
+specify that you only want to fetch a subset of refs using "Fetch Refs".
-When specifying branches, you should enter one branch name per line. You can
-use regular expressions to match branches by wrapping an expression in
-`regexp(...)`. For example:
+Normally, all refs (`refs/*`) are fetched. This means all branches, all tags,
+and all other refs.
-| Example | Effect |
-|---------|--------|
-| `master` | Track only `master`.
-| `regexp(/^release-/)` | Track all branches which start with `release-`.
-| `regexp(/^(?!temp-)/)` | Do not track branches which start with `temp-`.
+If you want to fetch only a few specific branches, you can list only those
+branches. For example, this will fetch only the branch "master":
+```
+refs/heads/master
+```
-Actions
-======
+You can fetch all branches and tags (but ignore other refs) like this:
-The **Actions** panel can configure notifications and publishing behavior.
+```
+refs/heads/*
+refs/tags/*
+```
+
+This may be useful if the remote is on a service like GitHub, GitLab, or
+Gerrit and uses custom refs (like `refs/pull/` or `refs/changes/`) to store
+metadata that you don't want to bring into Phabricator.
-Normally, Phabricator publishes notifications when it discovers new commits.
-You can disable publishing for a repository by turning off **Publish/Notify**.
-This will disable notifications, feed, and Herald (including audits and build
-plans) for this repository.
+**Permanent Refs**: To learn more about permanent refs, see:
-When Phabricator discovers a new commit, it can automatically close associated
-revisions and tasks. If you don't want Phabricator to close objects when it
-discovers new commits, disable **Autoclose** for the repository.
+ - @{article:Diffusion User Guide: Permanent Refs}
+
+By default, Phabricator considers all branches to be permanent refs. If you
+only want some branches to be treated as permanent refs, specify them here.
+
+When specifying branches, you should enter one branch name per line. You can
+use regular expressions to match branches by wrapping an expression in
+`regexp(...)`. For example:
+
+| Example | Effect |
+|---------|--------|
+| `master` | Only the `master` branch is a permanent ref.
+| `regexp(/^release-/)` | Branches are permanent if they start with `release-`.
+| `regexp(/^(?!temp-)/)` | Branches named `temp-` are not permanent.
Staging Area
============
The **Staging Area** panel configures staging areas, used to make proposed
changes available to build and continuous integration systems.
For more details, see @{article:Harbormaster User Guide}.
Automation
==========
The **Automation** panel configures support for allowing Phabricator to make
writes directly to the repository, so that it can perform operations like
automatically landing revisions from the web UI.
For details on repository automation, see
@{article:Drydock User Guide: Repository Automation}.
Symbols
======
The **Symbols** panel allows you to customize how symbols (like class and
function names) are linked when viewing code in the repository, and when
viewing revisions which propose code changes to the repository.
To take advantage of this feature, you need to do additional work to build
symbol indexes. For details on configuring and populating symbol indexes, see
@{article:User Guide: Symbol Indexes}.
Repository Identifiers and Names
================================
Repositories have several short identifiers which you can use to refer to the
repository. For example, if you use command-line administrative tools to
interact with a repository, you'll provide one of these identifiers:
```
$ ./bin/repository update <identifier>
```
The identifiers available for a repository depend on which options are
configured. Each repository may have several identifiers:
- An **ID** identifier, like `R123`. This is available for all repositories.
- A **callsign** identifier, like `rXY`. This is available for repositories
with a callsign.
- A **short name** identifier, like `xylophone`. This is available for
repositories with a short name.
All three identifiers can be used to refer to the repository in cases where
the intent is unambiguous, but only the first two forms work in ambiguous
contexts.
For example, if you type `R123` or `rXY` into a comment, Phabricator will
recognize them as references to the repository. If you type `xylophone`, it
assumes you mean the word "xylophone".
Only the `R123` identifier is immutable: the others can be changed later by
adjusting the callsign or short name for the repository.
Commit Identifiers
==================
Diffusion uses repository identifiers and information about the commit itself
to generate globally unique identifiers for each commit, like `rE12345`.
Each commit may have several identifiers:
- A repository **ID** identifier, like `R123:abcdef123...`.
- A repository **callsign** identifier, like `rXYZabcdef123...`. This only
works if a repository has a callsign.
- Any unique prefix of the commit hash.
Git and Mercurial use commit hashes to identify commits, and Phabricator will
recognize a commit if the hash prefix is unique and sufficiently long. Commit
hashes qualified with a repository identifier must be at least 5 characters
long; unqualified commit hashes must be at least 7 characters long.
In Subversion, commit identifiers are sequential integers and prefixes can not
be used to identify them.
When rendering the name of a Git or Mercurial commit hash, Phabricator tends to
shorten it to 12 characters. This "short length" is relatively long compared to
Git itself (which often uses 7 characters). See this post on the LKML for a
historical explanation of Git's occasional internal use of 7-character hashes:
https://lkml.org/lkml/2010/10/28/287
Because 7-character hashes are likely to collide for even moderately large
repositories, Diffusion generally uses either a 12-character prefix (which makes
collisions very unlikely) or the full 40-character hash (which makes collisions
astronomically unlikely).
Next Steps
==========
Continue by:
- returning to the @{article:Diffusion User Guide}.
diff --git a/src/docs/user/userguide/diffusion_permanent.diviner b/src/docs/user/userguide/diffusion_permanent.diviner
new file mode 100644
index 0000000000..fba4341c0c
--- /dev/null
+++ b/src/docs/user/userguide/diffusion_permanent.diviner
@@ -0,0 +1,81 @@
+@title Diffusion User Guide: Permanent Refs
+@group userguide
+
+Explains when Diffusion will take actions in response to discovering commits.
+
+Overview
+========
+
+Diffusion can close tasks and revisions and take other actions when commits
+appear in a repository (either because they were pushed to Phabricator, or
+because they were pushed to some remote which Phabricator is observing).
+
+This document explains when Diffusion acts on commits and how to configure this
+behavior.
+
+
+Publishing Commits
+==================
+
+Diffusion distinguishes between "pushed" and "published" commits.
+
+Not all commits that are pushed to a repository are destined for greatness:
+for example, many tools push temporary commits to secret places like
+`refs/pull/123`, `refs/notes/*`, or `refs/changes/12/345678/1`.
+
+Sometimes, human users intentionally push changes to branches like
+"tmp-hack-ignore-123". This is formally discouraged by Phabricator, but the
+practice is so widespread that we've given up trying to stop anyone from doing
+it.
+
+Phabricator will import these commits and create pages for them so you can view
+them in the web UI and link to them, but does not take any other actions until
+they are "published".
+
+A commit is "published" when it becomes reachable from a permanent ref. By
+default, all branches are permanent refs, so pushing a commit to "master" will
+publish it, but pushing a commit to `refs/pull/123` (either directly, or by
+using a tool like GitHub) will not.
+
+Usually, commits are published by pushing them directly to a permanent branch
+like "master", or by merging a temporary branch into a permanent branch.
+
+When a commit is published, Phabricator acts on it and:
+
+ - sends email;
+ - delivers notifications;
+ - publishes a feed story;
+ - triggers Audits;
+ - runs Herald rules;
+ - updates mentioned objects;
+ - closes referenced tasks; and
+ - closes associated revisions.
+
+
+Configuring Repositories
+========================
+
+You can control publishing behavior in two primary ways: by configuring
+which refs are considered to be permanent refs, and by disabling publishing
+entirely.
+
+By default, all branches are considered permanent refs and all other refs
+(including tags and other arbitrary custom refs) are considered nonpermanent.
+This means that, by default, pushing commits to a branch like
+"tmp-hack-ignore-123" will publish those commits.
+
+If you want to be free to push commits to temporary branches like this and
+only want commits on certain branches (like "master") to be published,
+configure which refs are treated as permanent by editing
+{nav Branches > Permanent Refs} from the "Manage" page of the repository.
+
+To disable publishing entirely, select {nav Basics > Disable Publishing}.
+
+
+Next Steps
+==========
+
+Continue by:
+
+ - troubleshooting in greater depth with
+ @{article:Troubleshooting Repository Imports}.
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 17:47 (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1127118
Default Alt Text
(63 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment