细读 Git | 让你弄懂 origin、HEAD、FETCH_HEAD 相关内容

一、远程名称(Remote Name)

在 Git 中,其实无论是 origin,还是 upstream 并没有特殊的含义,但由于被广泛使用,因此它们有了约定俗成、众所周知的含义。

如果我跟你说,以下两条命令是完全等效的,你是不是就差不多猜得出 origin 表示什么了?

$ git push origin master
$ git push https://gitee.com/jsxztshaohaibo/git-usage-test.git master

是的,跟你猜的一样:没有区别。

1.1 Origin

我们用示例来讲...

先在本地随意创建一个 Git 仓库 git-test,然后新增一个 ReadMe.md 文件,接着 Commit 一下

以上都没问题!接着,我们试着 Push 一下:

可以看到 git push 失败了.

原因很容易理解:我们只是在本地创建一个仓库,并没有将本仓库与远程仓库进行关联,因此 Git 无法理解是将其推送至哪个代码托管平台,然后也不知道是平台上的哪个远程仓库,是 GitHub 平台的,还是 GitLab 平台的?是平台上的 React 仓库,还是 Vue 仓库,还是别的什么仓库?Git 统统都不知道,那么自然是无法替你办事了。

因此,我们需要做的就是把本地的 git-test 仓库与远程仓库关联一下(请注意,一个本地仓库是可以关联多个远程仓库的):

$ git remote add origin <repo_address>

这里用到了 origin,我们先不管为什么用 origin,用其他(比如 main、abc)行不行的问题?(答案是可以的)

关联之后,再进行 Push 就能成功了。

 

那么 git remote add 内部做了什么默默无闻的工作呢,它其实是往 .git/config 中写入了一个叫 [remote "origin"] 配置:

[core]
	repositoryformatversion = 0
	filemode = false
	bare = false
	logallrefupdates = true
	symlinks = false
	ignorecase = true
[remote "origin"]
	url = https://gitee.com/jsxztshaohaibo/git-usage-test.git
	fetch = +refs/heads/*:refs/remotes/origin/*

如果你本地的仓库是通过 git clone 下来的,Git 会默认将远程仓库命名为 origin,自动帮你关联上远端仓库(可在 .git/config 文件中看到已有 [remote "origin"] 配置项了),因此 Commit 之后就能直接 Push 了。

我们来分析一下,这配置表示什么意思。

[remote "origin"]
	url = https://gitee.com/jsxztshaohaibo/git-usage-test.git
	fetch = +refs/heads/*:refs/remotes/origin/*

通过 git remote add 命令,添加了一个叫做 origin 的远程名称(Remote Name),

  • 其中 url 参数,表示该远程名称对应的远程仓库地址。
  • 其中 fetch 参数分为两部分,以冒号 : 进行分割,冒号左边表示本地仓库文件夹,冒号右边表示远程仓库在本地的副本文件夹。里面的加号 + 表示往里面添加数据的意思。

当使用 git fetch origin 时,Git 将远程仓库下的所有分支拉取到本地的 refs/remotes/origin/ 目录下,然后 git merge 时,它会把 refs/remotes/origin/ 目录下的对应分支合并到 refs/heads/ 目录下对应分支上。

那么 origin 究竟是什么呢?

请注意,origin 只是一个名称(别名),用于指向远程仓库。这个别名是可以自行修改的,比如命名为 foobar 等。使用别名好处是「简单、方便、好记(就像网址和IP的关系)」。

比起记住一个远程仓库地址,别名实在方便太多了。将 origin 作为远程仓库的别名是较为普遍的做法,况且所有代码托管平台默认就是 origin

回到文章开头的例子

$ git push origin master

# 相当于(其中 origin 指向了 https://gitee.com/jsxztshaohaibo/git-usage-test.git 远程仓库)
$ git push https://gitee.com/jsxztshaohaibo/git-usage-test.git master

以上两种方式是完全等价的,这样就更能体现别名的优势了,简洁很多。

既然是别名,自然是可以修改的,主要有以下命令:

# 新增远程名称(一个本地仓库,可以关联多个远程仓库)
$ git remote add <remote-name> <repo-address>

# 删除已存在远程名称(只会移除本地仓库与远程仓库的管理,不会删除远程仓库的代码哈)
$ git remote rm <remote-name>

# 更新远程名称关联的远程仓库
$ git remote set-url <remote-name> <repo-address>

# 修改远程名称(也可以先删除再添加)
$ git remote rename <old-remote-name> <new-remote-name>

比如使用 git remote set-url 修改关联的远程仓库地址:

然后,我们修改下远程名称为 main,也是可以的:

 接着,我们随意修改个文件 Push 一下,是这样的 git push main master

 到这里,你应彻底明白 origin 是什么了吧。

前面提到过,一个本地仓库是可以关联多个远程仓库的,举个例子:

我们新建一个远程仓库的地址,给新的仓库地址 起一个别名 origin

$ git remote add origin https://gitee.com/jsxztshaohaibo/git-usage-test.git

 从图中可以看到,别名 foo 和 bar 分别指向了两个不同的远程仓库,然后使用方法与 origin 是相同的,比如:

# 将本地的 master 分支推送至 main 对应的远程仓库(git-usage-test-02.gt)
$ git push main master 

# 将本地的 master分支推送至 origin 对应的远程仓库(git-usage-test.git)
$ git push origin master

 二、远程分支(Remote Branch)

常说的「远程分支」是远程仓库对应分支在本地的一个副本。比如常见的 origin/masterorigin/mainorigin/develop 等都是远程分支,可以在 .git/refs/remotes/ 目录下看到。

# 查看所有本地分支
$ git branch

# 查看所有远程分支(-r 是 --remotes 的简写)
$ git branch -r

# 查看所有本地分支和远程分支(-a 是 --all 的简写)
$ git branch -a

 可以通过 git branch -r 命令查看所有的远程分支:

 

上一节,我们介绍了远程名称只是一个代号、别名,是可以修改的。那么我们将 Remote Name 由 origin 修改为 foo,那么远程分支,会不会由 origin/main 变为 foo/main 呢?

 将远程名称修改之后,远程分支名称也会跟着改变的。

三、拉取最新代码

通常,拉取最新代码的过程是这样的: 

  • 通过 git fetch 拉取代码的过程:先读取 .git/config 文件里面的配置 [remote <remote-name>]将里面的所有因为 fetch 并没有指定其中一个或多个远程仓库)远程名称对应仓库的分支下载到本地,并放在 .git/refs/remotes/<remote-name>/ 目录下。

    比如 git fetch origin main 会创建或更新 .git/refs/remotes/origin/main 的文件,此时通过 git branch -r 就能看到一个 origin/main 的分支。但注意,我们使用的时候还是用 origin/main 而不是 remotes/origin/main 哦。

  • 有时候,我们可能会通过 git diff 命令来对比本地分支与远程分支的一些信息,才决定要不要合并。比如,git diff main origin/main

  • 通过 git mergegit rebase 来进行分支合并。比如 git merge origin/main,表示将远程分支 origin/main 合并至本地分支 main 中。

也可以直接使用 git pull 命令,其实包括了 git fetchgit merge 两个过程请注意 git fetch 并不会修改「本地分支」的代码。

细心的同学可能会发现,refs/remotes/origin/ 目录下,相应的分支文件记录的只是一个 Commit-ID(SHA-1),比较特殊的是 HEAD 文件(即 origin/HEAD 分支)记录的是 ref: refs/remotes/origin/main 的东西,它始终指向默认远程分支。

四、git 根据tag创建分支

现在主分支上有一个tag为v1.0.0,主分支的名字为master.

 1.执行:git origin fetch 获得最新.

 2.通过: git branch newbranch tagName 创建新分支

git branch newbranch v1.0.0.

 会以tag v1.0.0创建新的分支newbranch;

 3.再通过  git checkout newbranch 切换到新的分支. 

git checkout newbranch 

4.通过 git push origin newbranch 把本地创建的分支提交到远程仓库。

 git push origin newbranch

执行完以后,远程仓库也会有新创建的分支了。

<think>好的,我现在需要解释一下`git cherry-pick FETCH_HEAD`这个命令。首先,用户可能对Git的基本操作有一定了解,但可能不太清楚`cherry-pick`和`FETCH_HEAD`的具体用法。我需要先拆解这两个部分的作用,然后再结合起来解释整个命令的含义。 首先,`git cherry-pick`的作用是将某个提交应用到当前分支。这通常用于选择性地合并某个提交,而不是整个分支。用户可能知道`git merge`,但`cherry-pick`更灵活,可以挑选特定的提交。 接下来是`FETCH_HEAD`。这个文件记录了最近一次`git fetch`下载的各个分支的头指针。当用户执行`git fetch`时,远程分支的最新提交会被下载到本地,但不会自动合并,此时`FETCH_HEAD`会指向这些新获取的提交。用户可能对`git pull`更熟悉,但`fetch`只是获取并不合并,所以需要手动处理。 结合起来,`git cherry-pick FETCH_HEAD`的意思是将最近一次通过`git fetch`获取的远程分支的最新提交应用到当前分支。这相当于先获取远程更新,然后选择性地将那个最新提交应用到当前工作分支,而不是合并整个分支。 但需要确认是否正确。例如,如果用户执行了`git fetch origin some-branch`,那么`FETCH_HEAD`会指向`some-branch`的最新提交。这时候使用`cherry-pick`就会把这个提交应用到当前分支。但如果有多个分支被获取,`FETCH_HEAD`可能指向多个提交,这时候可能需要指定具体的提交哈希。 此外,用户可能会遇到冲突,这时候需要解决冲突并继续`cherry-pick`。可能需要提醒用户注意这一点,以及使用`git status`来查看解决冲突后的步骤。 总结来说,这个命令适用于只想应用远程仓库某个特定提交到当前分支的情况,而不是合并整个分支。这在协作开发中可能有用,比如需要某个热修复提交但不合并其他改动时。 需要验证是否有其他可能的误解,比如用户是否可能混淆`FETCH_HEAD`和`HEAD`,或者是否应该使用`git pull`来代替。但根据问题,用户明确询问的是`cherry-pick FETCH_HEAD`,所以应集中在正确解释这个命令上,而不是比较其他命令。 最后,确保用简洁明了的中文解释,避免技术术语过于复杂,同时覆盖常见使用场景和注意事项。</think>`git cherry-pick FETCH_HEAD` 是一个组合命令,结合了 Git 的 **`cherry-pick`** 操作和 **`FETCH_HEAD`** 的特殊引用。以下是分步解释: --- ### **1. 核心概念** - **`FETCH_HEAD`**: 当执行 `git fetch` 从远程仓库拉取更新时,Git 会将远程分支的最新提交记录在 `.git/FETCH_HEAD` 文件中。 **它指向最近一次 `git fetch` 获取的远程分支的最新提交**。 - **`git cherry-pick`**: 用于将某个特定的提交(commit)应用到当前分支,**相当于“复制”该提交的改动到当前分支**。 --- ### **2. 命令含义** `git cherry-pick FETCH_HEAD` 的实际操作是: **将最近一次 `git fetch` 获取的远程分支的最新提交,单独应用到当前分支**。 --- ### **3. 典型使用场景** - 你只想合并远程仓库某个分支的**最新提交**,而非整个分支的历史。 - 例如:远程仓库的 `main` 分支有一个紧急修复的提交,你希望仅将此修复复制到自己的分支,而不是合并整个 `main` 分支。 --- ### **4. 操作步骤** #### **(1) 拉取远程更新** ```bash git fetch origin # 从远程仓库 origin 拉取最新代码(不自动合并) ``` #### **(2) 查看 FETCH_HEAD 指向的提交** ```bash git log -1 FETCH_HEAD # 确认要应用的提交 ``` #### **(3) 应用该提交到当前分支** ```bash git cherry-pick FETCH_HEAD ``` --- ### **5. 注意事项** - **冲突风险**:如果目标提交的改动与当前分支有冲突,需手动解决(类似 `git merge`)。 - **单次生效**:`FETCH_HEAD` 仅指向最后一次 `git fetch` 的提交,多次 `fetch` 后会被覆盖。 - **精确控制**:若需选择多个提交,建议直接指定提交哈希(如 `git cherry-pick abc123`)。 --- ### **6. 替代方案对比** | 命令 | 行为 | |------|------| | `git merge FETCH_HEAD` | 合并远程分支的**所有新提交**到当前分支 | | `git cherry-pick FETCH_HEAD` | **仅合并远程分支的最新提交**到当前分支 | | `git pull` | `git fetch` + `git merge`(完整拉取并合并) | --- ### **7. 示例流程** ```bash # 假设你在本地分支 feature 工作 git checkout feature # 拉取远程 main 分支的更新(但暂不合并) git fetch origin main # 将远程 main 分支的最新提交单独应用到当前分支 git cherry-pick FETCH_HEAD ``` --- 通过这个命令,你可以更精准地控制代码合并,避免引入不必要的历史提交。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值