“弧形嫁接"和“弧形补丁"之间有什么区别? [英] What's the difference between `arc graft` and `arc patch`?

查看:124
本文介绍了“弧形嫁接"和“弧形补丁"之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

arc help --full | lessgraft揭示了这一点:

  graft revision

      Grafts revision and its dependencies (if any) onto your working tree.

      --force
          Do not run any sanity checks.

      --skip-landed
          Do not try to patch landed/closed diffs.

,而这是patch:

  patch D12345
  patch --revision revision_id
  patch --diff diff_id
  patch --patch file
  patch --arcbundle bundlefile
      Supports: git, svn, hg
      Apply the changes in a Differential revision, patchfile, or arc
      bundle to the working copy.

      --arcbundle bundlefile
          Apply changes from an arc bundle generated with 'arc export'.

这对我来说是模糊的.用嫁接"一词来描述嫁接"的含义对我没有多大帮助.


对于那些不了解的人,arc(Arcanist)是"Phabricator"内部的命令行工具,其作用类似于Git的高级包装(甚至是Mercurial和Subversion),以帮助开发大型软件项目的流程.这里有一些链接:

https://phacility.com/phabricator/

Phabricator最初是在Facebook上开发的内部工具.[7] [8] [9] Phabricator的主要开发人员是Evan Priestley.[1] Priestley离开了Facebook,继续在一家名为Phacility的新公司中继续Phabricator的开发.[2] https://en.wikipedia.org/wiki/Phabricator

解决方案

更新2020年3月19日:

请注意,arc flowarc cascade显然不是 Phacility奥术师的主流版本的一部分.相反,它们只是 Uber奥秘分叉的一部分.在此处.此外,arc cascade也是Uber的一个分支,它的某些arc cascade源代码位于 # cherry-pick their "D999" "diff" (branch) onto your current branch, while creating # a new single branch for you named "arcpatch-D999", skipping dependencies in case # they've already landed on the branch (ex: master) you currently have checked out. arc patch --skip-dependencies D999

OR

 # cherry-pick their "D999" "diff" (branch), *as well as all parent branch(es) it 
# depends on*, onto your current branch, while creating the entire dependency tree 
# of branches for you, exactly as the submitter originally had on their local 
# machine, skipping any commits that have already landed on your local branch 
# (ex: master) you currently have checked out
arc graft --skip-landed D999 
 


想象一下,您的arc flow依赖关系树仅包含"master"分支:

 master
 

但是,一位同事具有以下arc flow依赖关系树:

 master                              
└──new_feature_1
   └──new_feature_2 
 


简短地说:什么是arc flow依赖关系树?回答:这是一个树状结构,通过arc flow命令显示,该树结构显示了哪些分支取决于什么.作为一个人,您手动进行跟踪是有些武断的事情,因为您知道一个功能依赖于另一个功能.要建立依赖关系",您有两个选择:

  1. 在当前已签出要成为父级的分支时,调用arc flow new_branch_name创建一个新的子分支,或者:
  2. 使用git创建一个新分支,然后将其上游设置为您想要成为父分支的分支.例如:

     git branch new_branch_name
    git checkout new_branch_name # Or use `git checkout -b new_branch_name` to do both at once
    git branch --set-upstream-to=upstream_branch_name # or `git branch -u upstream_branch_name` for short
     

现在,arc flow将显示您的依赖关系树.这样一来,您可以像arc cascade这样从父级到子级进行操作,这只是从父级到子级进行自动递归git rebase(即:将子级重新定位到父级).

一旁结束.


无论如何,有了上面显示的依赖关系树,您的同事已签出"new_feature_2",并且他们arc diff进行审查.您转到基于Web的差异"工具并开始查看更改.但是,您要对其进行测试.这意味着您需要将它们的差异拉到本地计算机上.您有两个选择:1. arc patch它们的差异(依赖树感知分支)到本地主机,或者2. arc graft它们的差异到本地主机.

假设它们的差异为"D999",并且您当前已将"master"分支检出,则命令和生成的依赖关系树将如下所示:

  1. arc patch D999.现在,您有了这棵树,其中新创建的"arcpatch-D999"是其"new_feature_2"分支:

     master
    └──arcpatch-D999 
     

  2. arc graft D999.您现在拥有了这棵树,就像它们一样:

     master                              
    └──new_feature_1
       └──new_feature_2 
     

但是,(根据我的问题,我认为)有时候,当他们拥有像这样的多代依赖树时,arc patch将会失败(给出一个错误,指出"Cherry Pick Failed!").在这种情况下,您必须使用arc graft代替!但是,如果他们的主人与您的主人不完全相同(几乎可以肯定不会,因为他们可能将主人拉了一会儿,而您应该只是拉起主人,以确保您拥有最新的主人),那么您将尝试移植物或补丁将失败.失败可能与以下事实有关:分支历史中的某些提交包含已登陆并存在于您的主数据库中的更改. 解决方案是使用arc graft D999 --skip-landed,这将使您能够抓住他们的差异并将其拉下,从而镜像他们的arc flow依赖关系树.在这种情况下,arc patch D999可能会继续失败直到他们拉出最新的master和arc cascade(或git rebase两次),然后重新arc diff将他们的更改推送到服务器,这时您便可以arc patch D999成功地将其添加到您的master.但是,由于无法始终让它们立即重新变基/arc cascade,因此立即执行arc graft D999 --skip-landed即可!让他们重新定位并在到达时重新arc diff.

但是,一个小问题是,如果您arc graft的工作量很大,可能会混淆谁创建了哪个分支(您还是其他人?),因此我建议您养成嫁接到新分支上的习惯分支,为组织起自己的名字,如下所示:

 git checkout master # same as `arc flow master`
git pull origin master # pull latest master
arc flow graft-D999 # create and checkout a new child branch you are calling "graft-D999" (name it appropriately)
arc graft D999 --skip-landed # graft their entire dependency tree onto your branch "graft-D999"
 

您的依赖树现在将如下所示:

 master                              
└──graft-D999
   └──new_feature_1
      └──new_feature_2 
 

太好了!尼斯和有条理.现在,您可以签出"new_feature_2"并进行编译和测试.但是请注意,"master"和"graft-D999"将是完全相同的分支,但这没关系.

如何安装Uber的奥术师叉子

(以防您想在自己的git工作流程中开始使用arc flowarc cascade):

注意:Arcanist在Windows上运行(在Windows的 git 中git bash终端),Mac和Linux.我将只介绍Linux安装说明.要获得有关在其他系统中安装的帮助,请先查看下面的参考.

Linux Ubuntu安装:

cd到您希望安装文件存在的位置,然后执行以下操作:

 # 1. Obtain the Uber fork of the arcanist program by cloning it into an "uber" directory.
mkdir uber
git clone https://github.com/uber/arcanist.git uber
# 2. Symbolically link the `arc` program to your ~/bin directory so you can call `arc` from anywhere.
# - this assumes that ~/bin is in your PATH.
# Ensure the ~/bin dir exists; if just creating this dir for the first time you may need to log out of Ubuntu
# and log back in AFTER running the `mkdir` command below, in order to force your ~/.profile script to 
# automatically add ~/bin to your PATH (assuming your ~/.profile script does this, as default Ubuntu scripts do).
mkdir -p ~/bin
ln -s $PWD/uber/arcanist/bin/arc ~/bin
 

现在尝试运行arc.它应该失败,并显示以下消息:

 $ arc
ERROR: Unable to load libphutil. Put libphutil/ next to arcanist/, or update your PHP 'include_path' to include the parent directory of libphutil/, or symlink libphutil/ into arcanist/externals/includes/.
 

因此,请执行以下操作:

 # 3. Obtain the libphutil program.
# - Note that git cloning it like this `git clone https://github.com/phacility/libphutil.git` will NOT work anymore
# for Uber's fork of arcanist because the libphutil project is now empty. So, do this instead:
sudo apt install libphutil
# 4. symbolically link the libphutil program into arcanist.
# First, we need to know where it is installed.
dpkg -L libphutil
# Now look at the output from the above command. Mine shows libphutil is installed in "/usr/share/libphutil/",
# so do the following:
ln -s /usr/share/libphutil uber/arcanist/externals/includes
 

现在测试arc命令,您应该看到以下内容:

 $ arc
Usage Exception: No command provided. Try `arc help`.
 

运行arc help以查看帮助菜单,或单击arc help --full以获得完整的帮助菜单.

flowcascade的grep证明它们仅在Uber前叉的帮助菜单中(但不用于主要奥术师):

在完整的帮助菜单中查找flow:

 $ arc help --full | grep flow
          This workflow is primarily useful for writing scripts which integrate
              soft version of '' used by other workflows.
      flow [options]
      flow name [options]
      flow name upstream [options]
          step in the standard Differential pre-publish code review workflow.
          The workflow selects a target branch to land onto and a remote where
          Consulting mystical sources of power, the workflow makes a guess
          step in the standard Differential pre-publish code review workflow.
          The workflow selects a target branch to land onto and a remote where
          Consulting mystical sources of power, the workflow makes a guess
          code review workflow.
          The workflow selects a target branch to land onto and a remote where
 

cascade在完整的帮助菜单中:

 $ arc help --full | grep -A 4 cascade
      cascade [--halt-on-conflict] [rootbranch]

          Automates the process of rebasing and patching local working branches
          and their associated differential diffs. Cascades from current branch
          if branch is not specified.
--
              Rather than aborting any rebase attempts, cascade will drop the
              user
              into the conflicted branch in a rebase state.
 

参考:

  1. 设施的奥术师(缺少arc flowarc cascade功能): https://github.com/phacility /arcanist
  2. Uber的Arcanist分支(已添加arc flowarc cascade功能): https://github. com/uber/arcanist
  3. Arcanist用户指南: https://secure.phabricator.com/book/phabricator/article/arcanist/->有关如何在Windows,Mac,Linux或FreeBSD中进行安装的说明,请参见安装Arcanist"部分.
  4. 错误:无法加载libphutil

相关:

  1. 以类似时尚的树形式输出git分支

arc help --full | less reveals this for graft:

  graft revision

      Grafts revision and its dependencies (if any) onto your working tree.

      --force
          Do not run any sanity checks.

      --skip-landed
          Do not try to patch landed/closed diffs.

and this for patch:

  patch D12345
  patch --revision revision_id
  patch --diff diff_id
  patch --patch file
  patch --arcbundle bundlefile
      Supports: git, svn, hg
      Apply the changes in a Differential revision, patchfile, or arc
      bundle to the working copy.

      --arcbundle bundlefile
          Apply changes from an arc bundle generated with 'arc export'.

which is vague to me. Using the word "graft" to describe what "graft" means doesn't help me much.


For those who don't know, arc (Arcanist) is a command-line tool inside of "Phabricator" which acts like a high-level wrapper around Git (or even Mercurial and Subversion) to aid in the development process for large software projects. Here's a few links:

https://phacility.com/phabricator/

Phabricator was originally developed as an internal tool at Facebook.[7][8][9] Phabricator's principal developer is Evan Priestley.[1] Priestley left Facebook to continue Phabricator's development in a new company called Phacility.[2] https://en.wikipedia.org/wiki/Phabricator

解决方案

Update 19 Mar. 2020:

Note that arc flow and arc cascade are apparently not part of the mainstream version of Phacility's arcanist. Rather, they are only part of the Uber fork of arcanist. Some of the arc flow source code is found here, for instance. Additionally, arc cascade is also only an Uber fork arcanist feature, and some of its arc cascade source code is found here.
To learn how to install Uber's fork of arcanist in order to begin using these features in your regular git workflow (you don't need to use any other features of arcanist if not needed), jump to the bottom of this answer.


ORIGINAL ANSWER Jan. 2019:

So, after some experimenting and trial and error, I think I figured it out:

Both arc graft and arc patch use git cherry-pick under the hood, and accomplish similar things. However, they have some subtle differences, and sometimes arc patch fails and you must use arc graft with the --skip-landed flag instead (update: or perhaps arc patch with the --skip-dependencies flag will work too?).

Examples:

# cherry-pick their "D999" "diff" (branch) onto your current branch, while creating 
# a new single branch for you named "arcpatch-D999", skipping dependencies in case 
# they've already landed on the branch (ex: master) you currently have checked out.
arc patch --skip-dependencies D999 

OR

# cherry-pick their "D999" "diff" (branch), *as well as all parent branch(es) it 
# depends on*, onto your current branch, while creating the entire dependency tree 
# of branches for you, exactly as the submitter originally had on their local 
# machine, skipping any commits that have already landed on your local branch 
# (ex: master) you currently have checked out
arc graft --skip-landed D999 


Imagine your arc flow dependency tree only contains the "master" branch:

master

A coworker, however, has the following arc flow dependency tree:

master                              
└──new_feature_1
   └──new_feature_2 


Short aside: what's an arc flow dependency tree? Ans: it is a tree structure, shown via the arc flow command, which shows which branches depend on what. It is a somewhat arbitrary thing that you as a human are tracking manually, since you know that one feature depends on another. To establish a "dependency", you have two options:

  1. Call arc flow new_branch_name to create a new child branch while you have currently checked-out the branch you want to be the parent, OR:
  2. Use git to create a new branch, then set its upstream to what you want to be the parent. Ex:

    git branch new_branch_name
    git checkout new_branch_name # Or use `git checkout -b new_branch_name` to do both at once
    git branch --set-upstream-to=upstream_branch_name # or `git branch -u upstream_branch_name` for short
    

Now, arc flow will show your dependency tree. This allows you to to things like arc cascade from a parent down to its children, which is just doing automated recursive git rebases from parents down to children (ie: rebasing children onto parents).

End of aside.


Anyway, with the dependency tree shown above, your coworker has "new_feature_2" checked out, and they arc diff it for you to review. You go to the web-based "Differential" tool and start reviewing the change. However, you want to test it. This means you need to pull their diff to your local machine. You have two options: 1. arc patch their diff (dependency-tree-aware branch) onto your local master, or 2. arc graft their diff onto your local master.

Assuming their diff is "D999", and you currently have your "master" branch checked-out, your commands and resulting dependency trees would look as follows:

  1. arc patch D999. You now have this tree, where your newly-created "arcpatch-D999" is their "new_feature_2" branch:

    master
    └──arcpatch-D999 
    

  2. arc graft D999. You now have this tree, just like they have:

    master                              
    └──new_feature_1
       └──new_feature_2 
    

However, (I think, based on my problems) that sometimes when they have a multi-generation dependency tree like this, arc patch will fail (giving an error that says "Cherry Pick Failed!"), and in such a case you must use arc graft instead! HOWEVER, if their master is NOT the exact same as your master (which is almost certainly will NOT be, since they probably pulled their master a while back and you should have just pulled yours to ensure you have the latest), then your attempts to graft or patch will fail. It is likely the failures will be related to the fact that some of the commits in their branch history contain changes which are already landed and present in your master. The solution is to use arc graft D999 --skip-landed, which will allow you to grab their diff and pull it down, mirroring their arc flow dependency tree. In such a case, arc patch D999 will likely continue to fail until they pull the latest master and arc cascade (or git rebase twice), then re-arc diff to push their changes to the server, at which point you can then arc patch D999 onto your master successfully. Since you can't always get them to rebase/arc cascade immediately, however, just do the arc graft D999 --skip-landed now and be done! Let them rebase and re-arc diff when they get to it.

One minor problem, however, is that if you are arc grafting much, it can get confusing who made which branches (you, or someone else?), so I recommend you get into the habit of grafting onto a new branch you name yourself, as follows, just for organization:

git checkout master # same as `arc flow master`
git pull origin master # pull latest master
arc flow graft-D999 # create and checkout a new child branch you are calling "graft-D999" (name it appropriately)
arc graft D999 --skip-landed # graft their entire dependency tree onto your branch "graft-D999"

Your dependency tree will now be as follows:

master                              
└──graft-D999
   └──new_feature_1
      └──new_feature_2 

Excellent! Nice and organized. Now you can check out "new_feature_2" and compile and test it. Note, however, that "master" and "graft-D999" will be exactly identical branches, but that's ok.

How to install Uber's fork of arcanist

(in case you'd like to start using arc flow and arc cascade in your own git work-flows):

Note: Arcanist runs on Windows (inside the git for Windows git bash terminal), Mac, and Linux. I'll just present the Linux installation instructions. To get help on installing in other systems start by seeing the References below.

Linux Ubuntu installation:

cd to where you'd like the installation files to live, then do the following:

# 1. Obtain the Uber fork of the arcanist program by cloning it into an "uber" directory.
mkdir uber
git clone https://github.com/uber/arcanist.git uber
# 2. Symbolically link the `arc` program to your ~/bin directory so you can call `arc` from anywhere.
# - this assumes that ~/bin is in your PATH.
# Ensure the ~/bin dir exists; if just creating this dir for the first time you may need to log out of Ubuntu
# and log back in AFTER running the `mkdir` command below, in order to force your ~/.profile script to 
# automatically add ~/bin to your PATH (assuming your ~/.profile script does this, as default Ubuntu scripts do).
mkdir -p ~/bin
ln -s $PWD/uber/arcanist/bin/arc ~/bin

Now try to run arc. It should fail with the following message:

$ arc
ERROR: Unable to load libphutil. Put libphutil/ next to arcanist/, or update your PHP 'include_path' to include the parent directory of libphutil/, or symlink libphutil/ into arcanist/externals/includes/.

So, do the following:

# 3. Obtain the libphutil program.
# - Note that git cloning it like this `git clone https://github.com/phacility/libphutil.git` will NOT work anymore
# for Uber's fork of arcanist because the libphutil project is now empty. So, do this instead:
sudo apt install libphutil
# 4. symbolically link the libphutil program into arcanist.
# First, we need to know where it is installed.
dpkg -L libphutil
# Now look at the output from the above command. Mine shows libphutil is installed in "/usr/share/libphutil/",
# so do the following:
ln -s /usr/share/libphutil uber/arcanist/externals/includes

Now test the arc command and you should see the following:

$ arc
Usage Exception: No command provided. Try `arc help`.

Run arc help to see the help menu, or arc help --full for the full help menu.

Let's grep for flow and cascade to prove they are in the help menu for the Uber fork only (but not for the main arcanist):

Grepping for flow in the full help menu:

$ arc help --full | grep flow
          This workflow is primarily useful for writing scripts which integrate
              soft version of '' used by other workflows.
      flow [options]
      flow name [options]
      flow name upstream [options]
          step in the standard Differential pre-publish code review workflow.
          The workflow selects a target branch to land onto and a remote where
          Consulting mystical sources of power, the workflow makes a guess
          step in the standard Differential pre-publish code review workflow.
          The workflow selects a target branch to land onto and a remote where
          Consulting mystical sources of power, the workflow makes a guess
          code review workflow.
          The workflow selects a target branch to land onto and a remote where

And cascade in the full help menu:

$ arc help --full | grep -A 4 cascade
      cascade [--halt-on-conflict] [rootbranch]

          Automates the process of rebasing and patching local working branches
          and their associated differential diffs. Cascades from current branch
          if branch is not specified.
--
              Rather than aborting any rebase attempts, cascade will drop the
              user
              into the conflicted branch in a rebase state.

References:

  1. Phacility's Arcanist (lacks arc flow and arc cascade features): https://github.com/phacility/arcanist
  2. Uber's fork of Arcanist (has arc flow and arc cascade features added): https://github.com/uber/arcanist
  3. Arcanist User Guide: https://secure.phabricator.com/book/phabricator/article/arcanist/ --> See "Installing Arcanist" section for their instructions on how to install it in Windows, Mac, Linux, or FreeBSD.
  4. ERROR: Unable to load libphutil

Related:

  1. Output of git branch in tree like fashion

这篇关于“弧形嫁接"和“弧形补丁"之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆