为什么“从”是“从”? “git pull”中的行响应未列出裸存储库的名称?

发布于 2025-01-20 05:25:13 字数 2730 浏览 1 评论 0原文

我是Git的新手,我正在尝试了解

...
From /tvm
   f8322345..9837f82f  master     -> origin/master
...

Git对Git branch dev的响应中的响应。

我有一个裸露的仓库,还有两个将/拉到该酒吧仓库的存储库。全部在单个服务器上。配置如下:

/
|
+-- tvm.git           The bare repo
|
+-- htdocs
      |
      +-- dev         The development repo. Has both master and dev branches
      |
      +-- website     The production repo. A clone of the master branch.

该设置用于管理基于Joomla的网站。随着人们的撰写新文章等,数据库会发生变化,因此生产存储库中的主分支随之而来。

我需要将主分支合并到开发存储库中的开发分支机构中,以使开发人员保持最新状态。当在/htdocs/weblote中(始终具有分支Master检查)时,我首先卸载DB,然后git commitgit推。 git的响应是(有些行删除了一些行):

Enumerating objects: 5, done.
...
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
To /tvm.git
   5f08eef0..9837f82f  master -> master

我理解最后两行是指:git将更改推向了裸仓库(to /tvm.git < /code < /code>),这是分支 <代码>主

接下来,我更改为DevLopment目录,该目录具有分支dev检查。

/htdocs/website $ cd ../dev/
/htdocs/dev $ git status
On branch dev
Your branch is up to date with 'origin/dev'.

nothing to commit, working tree clean

可以肯定的是,我用git拉拉从裸露中拉出。响应是(再次被删除的一些行):

remote: Enumerating objects: 17, done.
...
Unpacking objects: 100% (13/13), 32.46 KiB | 21.00 KiB/s, done.
From /tvm
   f8322345..9837f82f  master     -> origin/master
Already up to date.

我不明白,首先,git为什么要告诉我来自 /tvm < /code>而不是< /code> < /tvm.git < /code> < /code>?这只是不一致吗?其次,为什么git Writing Master-&GT; Origin/Master?为什么而不是dev?第三,为什么git写作已经是最新的。?主分支是不是最新的;我刚刚承诺并推动了裸露的存储库中的主人分支。

git配置文件包含...

  • 在开发存储库中:
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = /tvm.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
[branch "dev"]
        remote = origin
        merge = refs/heads/dev
  • 在生产回购中:
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = /tvm.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
  • 在Bare Repo_中:
[core]
        repositoryformatversion = 0
        filemode = true
        bare = true

I'm rather new to git, and I'm trying to understand the lines

...
From /tvm
   f8322345..9837f82f  master     -> origin/master
...

in git's response to a git pull with branch dev checked out.

I've got a git bare repo, and two repos that push/pull to that bar repo; all on a single server. The configuration is as follows:

/
|
+-- tvm.git           The bare repo
|
+-- htdocs
      |
      +-- dev         The development repo. Has both master and dev branches
      |
      +-- website     The production repo. A clone of the master branch.

This setup is used to manage a Joomla based web site. The database changes as people are writing new articles, etc., so the master branch in the production repo changes with this.

I need to merge the master branch into the dev branch in the development repo to bring dev up to date. While in /htdocs/website (which always has branch master checked out), I first unload the DB, then git commit, and git push. Git's response is (some lines deleted for brevity):

Enumerating objects: 5, done.
...
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
To /tvm.git
   5f08eef0..9837f82f  master -> master

I understand the last two lines to mean: Git has pushed the changes to the bare repo (To /tvm.git) and this was branch master to master.

Next, I change to the devlopment directory, which has branch dev checked out.

/htdocs/website $ cd ../dev/
/htdocs/dev $ git status
On branch dev
Your branch is up to date with 'origin/dev'.

nothing to commit, working tree clean

Just to be sure, I pull from the bare with git pull. The response is (again some lines deleted):

remote: Enumerating objects: 17, done.
...
Unpacking objects: 100% (13/13), 32.46 KiB | 21.00 KiB/s, done.
From /tvm
   f8322345..9837f82f  master     -> origin/master
Already up to date.

I don't understand, firstly, why does git tell me From /tvm and not From /tvm.git? Is this just inconsistency? Secondly, why is git writing master -> origin/master? Why master and not dev? And thirdly, why is git writing Already up to date.? The master branch is not up to date; I had just commited and pushed changes to the master branch in the bare repo.

The git config files contain ...

  • In the development repo:
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = /tvm.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
[branch "dev"]
        remote = origin
        merge = refs/heads/dev
  • In the production repo:
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = /tvm.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
  • In the bare repo_:
[core]
        repositoryformatversion = 0
        filemode = true
        bare = true

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

阪姬 2025-01-27 05:25:13

首先,我不明白为什么 git 告诉我 From /tvm 而不是 From /tvm.git

Git 从 origin 读取 url = 设置(在本例中)并使用它,但它确实倾向于从 origin 中剥离 .git此类 URL 的末尾。这没有特别好的或坏的原因。 Git 就是这么做的。

其次,git为什么要写master ->起源/主人?为什么是master而不是[我所在的分支,即]dev

git pull 命令包含运行另外两个 Git 命令:1

  • 首先,git pull 运行 git fetch
  • 然后它运行另一个命令,我们暂时不考虑该命令。

(如果您确实提供了任何参数,那么您传递给 git pull 的大多数但不是全部参数都会直接转到 git fetch 。您没有提供,因此我们可以绕过所有参数血淋淋的细节在这里。)

git fetch 命令是产生这些输出行的命令。 fetch 命令:

  1. 调用其他一些 Git 存储库:无论提供的 URL 上有什么答案。通常,URL 以 https://ssh:// 开头,以便 Git 通过网络进行传输,有点像拨打网络电话。 Web 或 ssh 服务器将应答并将“电话呼叫”转移到其他 Git 软件,或者至少是其他使用 Git 协议的软件,这样现在就有两个单独的 Git 命令正在运行:您的、您的存储库上的和他们的,在他们的存储库上。

    在你的例子中,URL 是一个文件,所以你自己的 Git 软件扮演了其他 Git 软件的角色,而不是打电话给某人看谁回答。 (您的 Git 可能会也可能不会生成第二轮 Git 软件,具体取决于您所使用的所有内容的版本。传统的 C Git 确实(或至少确实)必须生成另一个版本,因为存在或至少曾经是,太多的全局变量,以至于只有一个存储库可以“发挥作用”,要么被读取(Git 服务于获取)要么被写入;随着时间的推移,这一问题至少大部分已经修复,因此细节可能会因 Git 版本而异。 )无论哪种方式原理都是一样的:你的 Git 服务器“调用”读取他们的存储库,而您的 Git写入您的 Git 存储库。

  2. 他们的 Git(他们的存储库上的软件)列出了他们的分支和标签以及其他此类名称以及与这些名称相关的提交哈希 ID。你的 Git 会挑选出它“喜欢”的那些。对于默认 git fetch,您的 Git 喜欢一切,因此您的 Git 看到的任何提交哈希 ID 您的 Git 还没有拥有,您的 Git请求他们的 Git 将其发送过来。这迫使他们提供该提交的父级;你的 Git 检查你是否有这些提交,如果没有,你的 Git 会要求这些提交,这使得他们的 Git 提供更多的父项,等等。

    此阶段对话的最终结果是,您的 Git 了解了他们拥有而您没有的每个提交,并且他们了解了重叠部分:你们都有哪些提交。然后,他们使用该信息打包您的 Git 需要的所有提交和支持对象,以便您将拥有他们拥有的一切以及您自己从未发送过的任何提交。 p>

    这涵盖了计数和枚举以及压缩和接收阶段。您的 Git 现在拥有所有必要的提交和支持对象,以便您拥有每个提交。你的 Git 会保存这些内容,并在必要时使用他们在拥有/想要对话阶段了解到的你已经拥有的对象来扩展(“解包”和“验证”等)内容。所有通信现已完成,您的 Git 软件可以与它们断开连接。

  3. 现在您已经拥有了他们的所有提交,您的 Git 将获取他们的每个分支名称并将其更改为您的远程跟踪名称:他们的 main 成为您的 origin/main,他们的 dev 成为您的 origin/dev,依此类推。请记住,在开始时,他们列出了所有他们的分支名称以及所有这些名称所代表的提交哈希 ID。

    您的 Git 现在会检查您的哪些 origin/* 名称需要创建或更新。这就是:

     f8322345..9837f82f 主控 ->起源/主人
    

    风格线条出来了。这意味着他们的 master(您的 origin/master)曾经将提交命名为 f8322345,但现在他们的 master 名称为 commit 9837f82f。因此,您的 Git 需要更新您自己的 origin/master

为了完全理解这一点,您还需要一个事实:任何提交的哈希 ID 都是普遍唯一的。如果您提交了 9837f82f的 Git 会调用 9837f82f他们的 Git 会调用 9837f82f,宇宙中所有其他拥有该提交的 Git 都将其称为 9837f82f。 (这个9837f82f实际上是从完整的哈希ID缩短的,它必须很大,这样它可以是普遍唯一的。)所以你的Git和他们的Git可以告诉哪些提交只要检查一下数字,你们就都知道了。 (哈希 ID 是提交内容的大型加密校验和的十六进制表示形式。2)

关于该行还有其他一些需要注意的事项:

   f8322345..9837f82f  master     -> origin/master

首先,请注意这两个点,以及该行并非以 (forced update) 结尾的事实。这意味着提交 f8322345 是提交 9837f82f祖先:父母、祖父母、曾祖父母、伟大 n-n > 的祖父母1。如果 master 被倒回并重写,您会看到一个加号、三个点,以及添加的强制更新备注。

如果您自己的 Git 还没有 origin/master,那么它们的 master 就存在(您的 origin/master< /code>)对于您的存储库来说是新的,您会得到:

 * [new branch]            master     -> origin/master

并且如果您在启用了修剪选项的情况下运行 git fetch 并且他们删除了一些分支名称,他们曾经有但不再这样做,你会得到:

 - [deleted]               (none)     -> origin/foo

这些因此,这些行会告诉您自上次从给定命名远程(如 origin)收集更新以来发生的情况。

第三,为什么 git 写的是已经是最新的了。

我们现在进入 git pull 将运行的第二命令。您可以选择此命令,但它(当前或之前至少3)默认为git merge。您的另一个选择是git rebase,但您将获得git merge

git fetch(获取所有其他 Git 分支名称)不同,4第二个 Git 命令 — 无论是哪一个您选择的一个 - 将仅在当前分支上运行。您当前的分支是 dev,其上游origin/devgit statusgitbranch -vv 命令将向您显示上游设置:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

这里我在我的 Git 存储库的 master 上,并且它与origin/master同步。由于我刚刚运行了 git fetch,这意味着 origin 的 master 标识了相同的提交:

$ git rev-parse master origin/master
ab1f2765f78e75ee51dface57e1071b3b7f42b09
ab1f2765f78e75ee51dface57e1071b3b7f42b09

我们在这里看到两个名称都标识了提交 ab1f2765f78e75ee51dface57e1071b3b7f42b09,即 Git 版本 2.36.0-rc1。

您的 git fetch 更新了您的 origin/master — 这就是您在 git pullgit fetch 输出中看到的内容 —但没有更新您的origin/dev。您现有的 dev 分支的提示提交与您的 origin/dev 提交相同或早于您的提交。这意味着 git merge他们方面没有任何工作可以与您可能已经完成的任何工作结合起来。您的 dev 已与您的 origin/dev 保持同步。这就是 Git 在这里告诉你的。


1过去,git pull 实际上只是一个实际运行 git fetch 的 shell 脚本,然后实际运行第二个 Git 命令。如今,它是一个庞大的 C 程序,在编译时,包含与 git fetch 和其他两个程序相同的代码,因此不必将其他程序作为命令调用,它以子例程调用的方式调用它们。不过原理是一样的,为了保持“向后兼容性”中的“向后”,C 代码顽强地经历了过去需要的每一个愚蠢的小问题,因为这些是单独的程序。

2目前这是一个 160 位 SHA-1 哈希,但事实证明 160 位 SHA-1 的加密强度毕竟不强,Git 正在向 256 位 SHA-256 迈进。另请参阅 Git 和 SHA-256

3这个默认值对许多人来说是坏/错误的,Git 现在开始要求您配置默认值。如果您收到关于需要配置 pull.ff 和/或 pull.rebase 的抱怨,那么您拥有的 Git 版本会促使您有意识地选择某些内容,而不仅仅是选择接受一些可能对您来说错误的默认设置。

4这实际上取决于多个细节,但默认设置是您获取所有分支,前提是您运行不带选项的 git fetch。请注意有关使用 git pull --all 的答案:这会将 --all 传递给 git fetch,这并不意味着 < em>所有分支,因为情况已经如此。相反,它意味着所有遥控器。这并不是有害,但它并没有起到人们认为的作用,因此推荐--all的答案应该谨慎对待,以免编写它们的人有其他有害的误解。


结论

git pull 是一个执行很多操作的大命令。它运行另外两个 Git 命令,每个命令也是一个执行很多操作的大命令:git fetch,然后是 git mergegit rebase首先研究所有这三个由 git pull 运行的命令是一个非常好的主意,并且在我看来,避免是一个好主意> git pull 倾向于运行各个命令,直到您对每个命令的作用有了很好的了解。

一旦您知道每个命令的作用,您可能会发现 git pull 的便捷捷径是运行 git fetch ,然后立即运行,而无需让您有机会观察什么git fetch 已获取 - 运行第二个命令就是您想要的。但在您知道自己想要什么之前,您实际上不会知道这一点,而在您知道其中每一个的作用之前,您是无法知道的。更糟糕的是,当其中一个命令失败时,您将不知道如何恢复。精通任何事物(软件、烹饪、木工、核反应堆操作等)的很大一部分在于知道当某些事情不起作用时该怎么做。当一切都按照设计进行时,任何傻瓜都可以做到;专业人士知道在不知道的情况下该怎么做。

I don't understand, firstly, why does git tell me From /tvm and not From /tvm.git?

Git reads the url = setting from origin (in this case) and uses that, but it does have a tendency to strip .git from the end of such URLs. There's no particularly good or bad reason for this. Git just does it.

Secondly, why is git writing master -> origin/master? Why master and not [the branch I am on, i.e.,] dev?

The git pull command consists of running two other Git commands:1

  • First, git pull runs git fetch.
  • Then it runs another command, which we'll leave out for a moment.

(Most but not all of the arguments you pass to git pull go directly to git fetch, if you do give any. You didn't, so we get to bypass all the gory details here.)

The git fetch command is the one producing these lines of output. The fetch command:

  1. Calls up some other Git repository: whatever answers at the URL provided. Typically the URL starts with https:// or ssh:// so that Git goes over the network, sort of like making an Internet phone call. A web or ssh server will answer and transfer the "phone call" to other Git software, or at least, other software that speaks the Git protocol, so that there are now two separate Git commands running: yours, on your repository, and theirs, on their repository.

    In your case the URL is for a file, so instead of calling someone to see who answers, your own Git software plays the role of the other Git software. (Your Git may or may not spawn a second round of Git software, depending on what version of everything you're using. Traditional C Git does, or at least did, have to spawn another one because there are, or at least were, too many global variables so that only one repository could be "in play", being either read—the Git serving the fetch—or written; this has at-least-mostly-fixed over time so the details may vary depending on Git version.) The principle is the same either way: the server your Git "calls up" reads their repository, and your Git writes to your Git repository.

  2. Their Git (their software on their repository) lists out their branches and tags and other such names and the commit hash IDs that go with these. Your Git picks out the ones it "likes". For a default git fetch, your Git likes everything, so any commit hash IDs your Git sees that your Git does not already have, your Git asks their Git to please send that over. This obliges them to offer that commit's parent(s); your Git checks to see if you have these commits, and if not, your Git asks for those, which makes their Git offer more parents, and so on.

    The end result of this phase of the conversation is that your Git learns about every commit they have that you don't, and they learn about the overlap: which commits you both have. They then use that information to package up all the commits and supporting objects that your Git will need, so that you will have everything they have plus any commits of your own that you have never sent out.

    This covers the counting and enumerating and compressing and receiving phases. Your Git now has all the necessary commits and supporting objects so that you have every commit. Your Git saves these away, expanding ("unpacking" and "verifying" and so on) things if/as necessary, using the objects you already have, that they learned about during the have/want conversation phase. All the communications are done now, and your Git software can disconnect from theirs.

  3. Now that you have all of their commits, your Git takes each of their branch names and changes those into your remote-tracking names: their main becomes your origin/main, their dev becomes your origin/dev, and so on. Remember, at the start of this, they listed out all their branch names and all the commit hash IDs that those names represented.

    Your Git now checks to see which of your origin/* names need creating or updating. This is where the:

       f8322345..9837f82f  master     -> origin/master
    

    style lines come out. This means their master—your origin/master—used to name commit f8322345, but now their master names commit 9837f82f. Your Git therefore needs to update your own origin/master.

To make complete sense of this, you need one more fact: the hash ID of any commit is universally unique. If you have commit 9837f82f, your Git calls that 9837f82f, their Git calls that 9837f82f, and every other Git in the universe that has that commit calls it 9837f82f. (This 9837f82f is actually shortened from the full hash ID, which has to be huge so that it can be universally unique.) So your Git and their Git can tell which commits you both have, just by examining the number. (The hash ID is a hexadecimal representation of a large cryptographic checksum over the commit's content.2)

There are a few other things to observe about the line:

   f8322345..9837f82f  master     -> origin/master

First, note the two dots, and the fact that the line does not end with (forced update). That means that commit f8322345 is an ancestor of commit 9837f82f: parent, or grandparent, or great-grand-parent, or greatn-grand-parent for n > 1. If master had been rewound and rewritten, you'd see a plus sign, three dots, and the added forced update remark.

If your own Git did not have an origin/master yet, so that the existence of their master (your origin/master) were new to your repository, you would get:

 * [new branch]            master     -> origin/master

and if you run git fetch with the prune option enabled and they have deleted some branch name they used to have but no longer do, you would get:

 - [deleted]               (none)     -> origin/foo

These lines therefore tell you a lot about what has happened since the last time you collected updates from a given named remote like origin.

And thirdly, why is git writing Already up to date.?

We now get into the second command that git pull will run. You get to choose this command, but it (currently, or previously at least3) defaults to being git merge. Your other option is git rebase, but you're getting git merge.

Unlike git fetch, which fetches all the other Git's branch names,4 the second Git command—regardless of which one you choose—will only operate on the current branch. Your current branch is dev and its upstream is origin/dev. The git status and git branch -vv commands will show you the upstream setting:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Here I'm on my master for my Git repository for Git, and it's in sync with origin/master. Since I just ran git fetch, that means origin's master identifies the same commit:

$ git rev-parse master origin/master
ab1f2765f78e75ee51dface57e1071b3b7f42b09
ab1f2765f78e75ee51dface57e1071b3b7f42b09

We see here that both names identify commit ab1f2765f78e75ee51dface57e1071b3b7f42b09, which is Git version 2.36.0-rc1.

Your git fetch updated your origin/master—that's what you saw in the git fetch output from git pull—but did not update your origin/dev. Your existing dev branch's tip commit is either the same as, or ahead of, your origin/dev commit. This means git merge has no work on their side to combine with any work you may have done on your side. Your dev is already up to date with your origin/dev. And that's what Git told you here.


1In the past, git pull was literally just a shell script that actually ran git fetch, then actually ran a second Git command. These days it's a big hairy C program that at compile time, includes the same code as git fetch and both other programs, so that instead of invoking the other programs as commands, it invokes them as subroutine calls. The principle is the same, though, and to keep the "backwards" in "backwards compatibility", the C code doggedly goes through every last silly little wrinkle that used to be required because these were separate programs.

2This is currently a 160-bit SHA-1 hash, but it turns out that 160 bits of SHA-1 is not cryptographically strong after all, and Git is moving towards 256-bit SHA-256. See also Git and SHA-256.

3This default turns out to be bad/wrong for many, and Git is now starting to require that you configure a default. If you get a complaint about needing to configure pull.ff and/or pull.rebase, you have a version of Git that's pushing you to pick something consciously, rather than just accepting some default that might be wrong for you.

4This actually depends on multiple details, but the default setup is that you get all branches, provided you run git fetch without options. Watch out for answers that talk about using git pull --all: this passes --all to git fetch, where it does not mean all branches since that's already the case. Instead, it means all remotes. This is not harmful, but it does not do what people think it does, so answers recommending --all should be treated with caution, lest the person who wrote them have other misunderstandings that are harmful.


Conclusion

git pull is a big command that does a lot. It runs two other Git commands, each of which is also a big command that does a lot: git fetch, then one of git merge or git rebase. It's a very good idea to study all three of these run-by-git pull commands first, and in my opinion, a good idea to avoid git pull in favor of running the individual commands, until you have a good working knowledge of what each one does.

Once you know what each command does, you may find that git pull's convenience short-cut of running git fetch and then immediately—without giving you a chance to observe what git fetch fetched—running a second command is what you want. But you won't actually know that until you know what you want, which you can't know until you know what each of these does. Worse, when one of the commands fails, you won't know how to recover. A huge part of being skilled with anything (software, cooking, woodworking, nuclear reactor operation, and so on) lies in knowing what to do when something didn't work. When everything works as designed, any fool can do it; the pros know what to do when it doesn't.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文