在不使用refspec参数的情况下运行git push,pull和fetch [英] Run git push, pull and fetch without refspec argument

查看:57
本文介绍了在不使用refspec参数的情况下运行git push,pull和fetch的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Loeliger 2ed的《使用Git进行版本控制》中,

From Version Control with Git by Loeliger 2ed,

如果您完全没有在 git push 命令上指定refspec怎么办?如何 Git知道该怎么做或在哪里发送数据吗?

What if you don’t specify a refspec at all on a git push command? How does Git know what to do or where to send data?

首先,在没有为命令提供明确的远程控制的情况下,Git假定 您想使用原点.

First, without an explicit remote given to the command, Git assumes you want to use origin.

没有参考说明 git push 会将您的提交发送到远程的所有分支之间的分支 存储库和上游存储库.任何非本地分支机构 上游存储库中已经存在的将不会向上游发送; 分支必须已经存在并且与名称匹配.

Without a refspec, git push will send your commits to the remote for all branches that are common between your repository and the upstream repository. Any local branch that is not already present in the upstream repository will not be sent upstream; branches must already exist and match names.

  • 都是全部 您的存储库和上游存储库之间共有的分支是否与本地存储库中的所有远程跟踪分支以及远程存储库中的相应跟踪分支相同?

    • Are "all branches that are common between your repository and the upstream repository" the same as all the remote-tracking branches in the local repository and the corresponding tracked branches in the remote repository?

      引号用于git push. 它是否适用于(git fetch)和git pull(尤其是没有refspec的情况下的部分)?

      The quote is for git push. Does it (especially the part for the case without a refspec) apply to git fetch and to git pull?

      推荐答案

      (恐怕这个答案又会很长,因为这些问题至少在今天是不正确的.实际答案,但在此之前的所有内容也很重要.)

      (I'm afraid this answer is once again rather long, because the questions make assumptions that are—at least today—incorrect. Jump to the boldface section for the actual answers, but everything that comes before that also matters.)

      您引用的书文本已经过时,并且现在(现在)完全是错误的(这对软件的发展是一种危​​害,书已经过时了):

      The book text you quote is outdated and (now) just plain wrong (this is a hazard with evolving software, the books get outdated):

      首先,在没有为命令提供明确的远程控制的情况下,Git假定您要使用origin.

      First, without an explicit remote given to the command, Git assumes you want to use origin.

      在git自己的git历史上相对快速的扫描中,我还没有准确地发现行为的更改时间,但是git 1.8.2.1中的 documentation 更改了,并且现在说:

      I have not, in a relatively quick scan through git's own git history, found precisely when the behavior changed, but the documentation changed in git 1.8.2.1, and now says:

      当命令行未指定使用 <repository>自变量,branch.*.remote配置 咨询当前分支以确定将推送到何处.如果 配置丢失,默认为原始.

      When the command line does not specify where to push with the <repository> argument, branch.*.remote configuration for the current branch is consulted to determine where to push. If the configuration is missing, it defaults to origin.

      (此行为也与git fetch匹配-毫不奇怪,因为它们使用相同的源代码位来获得该结果.)这没有提及可选的branch.$branch.pushremote设置,该设置覆盖了branch.$branch.remote.在所有情况下, $branch 代表您当前的分支,如git symbolic-ref --short HEAD的输出所示. (如果您处于分离式HEAD"模式,则git symbolic-ref失败,git push通常会向您显示致命:您当前不在分支上"错误,我认为自2.0版以来,默认值已更改.)

      (This behavior matches git fetch as well—unsurprisingly, since they use the same bit of source code to get that result.) This fails to mention the optional branch.$branch.pushremote setting, which overrides branch.$branch.remote. In all cases here $branch represents your current branch, as shown by the output of git symbolic-ref --short HEAD. (If you're in "detached HEAD" mode, so that git symbolic-ref fails, git push normally gives you a "fatal: You are not currently on a branch" error, I think since version 2.0 when the defaults changed.)

      这还不是全部,而是全部. git-config文档又添加了一个怪癖:

      This is still not the whole story; the git-config documentation adds yet one more quirk:

      remote.pushDefault
      默认情况下要推送到的遥控器.覆盖branch.<name>.remote 对于所有分支,并被branch.<name>.pushRemote覆盖 特定分支.

      remote.pushDefault
      The remote to push to by default. Overrides branch.<name>.remote for all branches, and is overridden by branch.<name>.pushRemote for specific branches.

      (幸运的是,到目前为止,我 think 涵盖了所有内容.也就是说,git首先为当前分支寻找pushremote设置.如果没有这样的设置,则接下来查找remote.pushdefault.如果还没有设置,它将退回到当前分支的remote设置.git的旧版本中的行为可能会有所不同.注意配置项不区分大小写:pushremotepushRemote是相同的配置名称[这使我想知道分支名称部分是否也不区分大小写;我必须在某个时候进行测试].

      (Fortunately, as of today, I think that covers everything. That is, git starts by looking for a pushremote setting for the current branch. If there is no such setting, it next looks for remote.pushdefault. If that is also not set, it falls back on the remote setting for the current branch. The behavior in older versions of git may vary. Note also that configuration items are case-insensitive: pushremote and pushRemote are the same configuration name [this makes me wonder if the branch name parts are case-insensitive as well; I'll have to test that out sometime].)

      关于refspecs的下一部分甚至更加错误,因为git随时间获得了一些更改,即使git的内置文档中也没有很好地记录其中的一些内容.你的报价写着:

      The next part about refspecs is even more wrong, due to git having acquired several changes over time, some of which are not documented well even in git's built-in documentation. Your quote reads:

      在没有refspec的情况下,git push会将您的提交发送到远程存储库和上游存储库之间公用的所有分支.

      Without a refspec, git push will send your commits to the remote for all branches that are common between your repository and the upstream repository.

      新文档说:

      当命令行未指定要使用<refspec>...推送的内容时 参数或--all--mirror--tags选项,该命令将找到 通过咨询remote.*.push配置获得默认的<refspec>, 如果找不到,则使用push.default配置来决定 推送内容(请参见 git-config push.default的含义.

      When the command line does not specify what to push with <refspec>... arguments or --all, --mirror, --tags options, the command finds the default <refspec> by consulting remote.*.push configuration, and if it is not found, honors push.default configuration to decide what to push (See git-config for the meaning of push.default).

      push.default设置是在git版本1.8左右添加的,但其默认 value 在git 2.0中已更改.如果尚未配置push.default,则会收到以下警告:

      The push.default setting was added around version 1.8 of git, but its default value changed in git 2.0. If you have not configured a push.default you get this warning:

      warning: push.default is unset; ...
      

      自配置项可用以来.咨询 git-config文档,您将现在找到这个:

      ever since the configuration item became available. Consulting the git-config documentation, you will now find this:

      push.default
      定义在未明确给出refspec的情况下git push应该执行的操作.不同的值非常适合特定的工作流程...

      push.default
      Defines the action git push should take if no refspec is explicitly given. Different values are well-suited for specific workflows ...

      有五个选项,我将在这里简单列出(有关详细信息,请参见链接的文档):nothingcurrentsimpleupstreammatching.您引用的书中的文字描述了matching,这是git版本2.0之前的默认行为.新的默认值为simple.

      There are five options, which I will simply list here (see the linked documentation for details): nothing, current, simple, upstream, and matching. The book text you quote describes matching, which was the default behavior prior to git version 2.0. The new default is simple.

      您的存储库和上游存储库之间共有的所有分支"是否与本地存储库中的所有远程跟踪分支以及远程存储库中的相应跟踪分支相同?

      Are "all branches that are common between your repository and the upstream repository" the same as all the remote-tracking branches in the local repository and the corresponding tracked branches in the remote repository?

      否.

      我建议您尝试运行git ls-remote origin(或将origin替换为任何其他遥控器的名称):

      I recommend that you try running git ls-remote origin (or replace origin with the name of any other remote):

      $ git ls-remote origin
      28274d02c489f4c7e68153056e9061a46f62d7a0        HEAD
      1ff88560c8d22bcdb528a6629239d638f927cb96        refs/heads/maint
      28274d02c489f4c7e68153056e9061a46f62d7a0        refs/heads/master
      0ac5344e619fec2068de9ab2afdb99d1af8854be        refs/heads/next
      5467631257c047b16d95929559dd1887d27b0ddc        refs/heads/pu
      68a0f56b615b61afdbd86be01a3ca63dca70edc0        refs/heads/todo
      d5aef6e4d58cfe1549adef5b436f3ace984e8c86        refs/tags/gitgui-0.10.0
      3d654be48f65545c4d3e35f5d3bbed5489820930        refs/tags/gitgui-0.10.0^{}
      [snip -- lots more omitted]
      

      然后,尝试git for-each-ref refs/heads:

      $ git for-each-ref refs/heads
      

      您将看到类似的输出,但是具有不同的SHA-1,并且单词commit夹在中间.

      You'll see similar output, but with different SHA-1s, and the word commit sandwiched in the middle.

      这里的要点是,在refs/heads中列出的每个头"(在来自ls-remotefor-each-ref的两个输出中)都表示git push在进行匹配"时考虑的(本地)分支.匹配的头将添加到推式列表中,提供一组refspec(内部形式,但很容易表示为 name:name ,或者,如果使用了--force标志,则表示为+name:name).

      The main point here is that each "head" listed in refs/heads—in both outputs, from ls-remote and from for-each-ref—represent the (local) branches that git push considers when doing "matching". The heads that match are added to the push list, giving the set of refspecs (in internal form but easily expressed as name:name or, if you used the --force flag, +name:name).

      即使没有为这些本地分支配置上游,也会发生 .因此,如果他们(远程)具有供鲍勃·罗伯茨使用的refs/heads/bob,并且您要使用refs/heads/bob来获取有关水管鲍勃,钓鱼鲍勃或其他东西的信息,则git会尝试匹配即使您的bob并非本意是上游的.

      This happens even if there is no upstream configured for those local branches. Thus, if they (the remote) have a refs/heads/bob that's meant for Bob Roberts to use, and you have a refs/heads/bob that you're using for information about your plumbing bobs or fishing bobbers or whatever, git will attempt to match those up even though your bob is not meant to go upstream.

      报价为git push.它是否适用(特别是没有refspec的情况下的部分)是否适用于git fetchgit pull?

      The quote is for git push. Does it (especially the part for the case without a refspec) apply to git fetch and to git pull?

      否.

      git fetch的行为更容易解释,因为它不能像git pull那样对您产生所有怪异的作用. git pull命令应该很方便,但是git pull试图将基本在存储库范围内的获取"操作与基本受分支约束的合并"操作混在一起.这两个不能很好地配合使用. 1 (充其量,我认为可以在某些时候修改git pull以进行更简单的,整个存储库范围内的全部提取,然后以逐对的方式签出并合并,某些分支基于跟踪配置和参数"序列.我认为这将使其行为像大多数人期望的那样.它也大多是向后不兼容的,并且行为仅适用于现在最简单(但默认)的情况是:先提取所有内容,然后仅合并当前分支.但这全都是推测.)

      The behavior of git fetch is easier to explain, because it doesn't do all the weird stuff on you that git pull does. The git pull command is supposed to be convenient, but git pull is trying to mash a fundamentally repository-wide "fetch" operation together with a fundamentally branch-constrained "merge" operation. These two do not play well together.1 (At best, I think git pull could at some point be modified to do a simpler, repository-wide "fetch all, then check out and merge, pairwise, some branch(es) based on tracking configs and arguments" sequence. I think this would make it behave the way most people seem to expect it to. It would also be mostly backwards-incompatible, and behave the way it does now only for the simplest—but default—case: fetch all, then merge current branch only. But that's all speculation anyway.)

      如果省略所有refspec,则git fetch会读取您的remote.$remote.fetch配置行.(请注意,此忽略所有refspecs"子句意味着您还必须避免使用方法.)

      If you omit all refspecs, git fetch reads your remote.$remote.fetch configuration lines. (Note that this "omit all refspecs" clause means you must also avoid the old "Named file in $GIT_DIR/branches" method, for instance.)

      名为origin的远程服务器的默认配置行(单数)通常如下所示(查看本地存储库配置文件以查看它):

      The default configuration line (singular) for a remote named origin usually looks like this (view your local repository configuration file to see it):

      [remote "origin"]
          +refs/heads/*:refs/remotes/origin/*
      

      这是远程跟踪分支"成立的实际机制.

      This is the actual mechanism by which "remote-tracking branches" come into existence.

      fetch过程从相同的git ls-remote origin步骤开始,该步骤从远程获取每个引用的列表(分支,标签或您拥有的内容). fetch代码继续将它们与[remote "origin"]下的每个fetch =行匹配. refspec左侧的星号具有明显的含义;右侧的星号将替换为左侧的星号匹配的内容. (在当前版本的git中,*必须与整个部分"匹配,松散地定义为斜线之间的填充",但是在即将到来的git中,此约束将得到放松-尽管我不确定达到什么目的.)

      The fetch process starts off with that same git ls-remote origin step, which gets a list of every reference—branch, tag, or what-have-you—from the remote. The fetch code goes on to match these up with each of the fetch = lines under [remote "origin"]. Asterisks on the left side of a refspec have the obvious meaning; asterisks on the right side are replaced with whatever the left-side asterisk matched. (In current versions of git the * must match a "whole part", loosely defined as "stuff between slashes", but in the upcoming git this constraint will be relaxed—though I'm not sure to what useful end.)

      您可能会喜欢任意多的fetch =行.每个原始引用都在每一行中运行,以获取新的(替换)引用:如果左侧匹配,则右侧提供替换. (如果右侧缺少或为空,则由于历史原因,该行为会变得有些奇怪,部分原因是保持git pull正常运行,部分原因是所需行为在git 1.8左右变化.)

      You may have as many fetch = lines as you like. Each original reference is run through each line to get a new (replacement) reference: if the left side matches, the right side provides the replacement. (If the right side is missing or empty, the behavior gets a bit weird for historical reasons, partly to keep git pull working, partly because the desired behavior changed around git 1.8 or so.)

      所有这些替换的结果形成重命名的引用,并确定完全复制了哪些引用;但每个原始引用最多只能有一个结果:您不能将其"引用/heads/foo映射到您的"引用/remotes/origin/bar ,而您的引用/remotes/例如起源/动物园.

      The results of all these replacements form the renamed references, and determine which references are copied at all; but there must be at most one result for each original reference: you can't map "their" refs/heads/foo to "your" refs/remotes/origin/bar and your refs/remotes/origin/zoink, for instance.

      要使存储库充当镜像,您可以使用+refs/*:refs/*来带入所有引用而无需重命名(但这会破坏每个fetch上的本地分支,因此仅在--bare下才有意义)

      To make a repository act as a mirror, you can use +refs/*:refs/* to bring over all references with no renaming (but this will clobber your local branches on each fetch so this mostly makes sense only with --bare).

      (修剪"(基于在启动协商期间对方为获取或推送而发送的内容删除死"引用,这是单独完成的,并且仅当您设置了--prune标志时才可以.)

      ("Pruning"—removing "dead" references based on what the other side sent during the startup negotiations for a fetch or push—is done separately and only if you set the --prune flag.)

      1 它不是以这种方式开始的.实际上,原始的pull脚本完全早于远程和远程跟踪分支.提交 7ef76925d9c19ef74874e1735e2436e56d0c4897 pull拆分为pullfetch,然后随着时间的流逝,两个方向朝着不同的方向发展;一旦远程"和远程跟踪分支"出现了,它们就演变为试图将它们混合在一起的想法,我认为这只是一个坏主意,而现在变得更糟了. :-)

      1It didn't start out this way. In fact, the original pull script predated remotes and remote-tracking branches entirely. Commit 7ef76925d9c19ef74874e1735e2436e56d0c4897 split pull into pull and fetch and then the two evolved in different directions over time; once "remotes" and "remote-tracking branches" came into existence, they'd evolved to the point that trying to mix them was, I think, just a bad idea, and now it's even worse. :-)

      这篇关于在不使用refspec参数的情况下运行git push,pull和fetch的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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