git推送错误:src refspec main在Linux上没有匹配任何内容。

59
每当我尝试使用git push -u origin main上传文件时,我会收到以下错误信息。
error: src refspec main does not match any
error: failed to push some refs to 'github.com:xxxxxx/xxx-project.git'

但是,如果我执行git push -u origin master,它完美地工作并将我的文件上传到名为master的单独分支。在检查我的项目中的.git/refs/heads时,我看到只有一个名为master的文件,因此我执行了git remote update,它添加了.git/refs/remotes/origin/main,但是git push -u origin main仍然无法工作。

我尝试了git push origin HEAD:main,但产生了错误:

![rejected] HEAD -> main(非快进)错误:未能将某些引用推送到'github.com:xxxxxxx/xxx-project.git'提示:更新被拒绝,因为推送的分支提示:提示后面的分支端点落后于其远程提示:同行。在再次推送之前,请检查此分支并集成远程更改提示:(例如“ git pull ...”)。详细了解有关快进的说明,请参见“ git push --help”中的“有关快进的说明”。

我想使用git push -u origin main将我的代码推送到主分支。 我该如何做?

P.S- git版本为2.29.2,pop_os 20.10.1

编辑1-git push -f origin HEAD:main将我的代码推送到main分支,但是我该如何替换refs/heads中的master文件与main文件,以便我不必提及head并强制推送?

9个回答

80
这是一个多部分答案,因为这里有两个独立的问题现在纠缠在一起了。以下是我们将要涵盖的内容概述:
- main与master - error: src refspec main does not match any - 协调单独的main和master分支
每个部分都有自己的章节。
main与master Git本身没有特殊的分支名称。你可以使用main、master、trunk或任何其他名称作为第一个分支的名称。Git传统上使用master名称,但有一个项目使其可配置,因此如果您是法国人或西班牙人,则可以使用principal、première或primero等名称,或者如果您更喜欢毛利语,则可以使用matua或tuatahi。目前,您可以在git init期间或之后手动执行此操作,但是该项目使Git自动执行此操作,而无需进行第二步操作:如果由于任何原因您想要使用默认情况下的任何其他名称,则可以对其进行配置。
同时,GitHub已经选择超前并将其默认初始分支名称从master更改为main。但是,这会使您的Git和GitHub的Git不同步。有关GitHub变更的更多信息,请参见Difference Between Main Branch and Master Branch in Github?

1这种说法存在一些技术上的缺陷。我们知道,技术上正确是最好的正确,所以让我在这个脚注中添加一些警告:

  • 当你在分支Y上运行git merge X时,合并会自动生成一个形如merge branch X into Y的消息。然而,当你在master上时,Git传统上只生成一个形如merge branch X的消息。

  • 通过git init创建的新空仓库没有提交,因此也没有分支(因为分支只能通过有提交来存在)。但是,在这个新的空仓库中,你必须某个分支上。所以 Git 在符号引用HEAD中存储了某个名称。即使该分支名称尚不存在,你也在该分支上。长期以来,Git 已经将分支名称master硬编码到其中。(这实际上就是 GitHub 所做的改变)

  • 还有很多源代码和文档中的其他字符串字面量都包含master;它们正在转换为使用配置设置,但这需要时间。

2如果你安装了 Git 2.28 或更高版本,可以运行git init --initial-branch=name,并使用git config在系统或全局配置中设置init.defaultBranch。如果你安装的是早期版本的 Git,或者已经运行了git init,只需使用git branch -mmaster重命名为你喜欢的任何名称即可。


错误:src refspec main does not match any

这是Git的错误信息,对新手来说可能有些晦涩,但实际上很简单。问题在于它充斥着术语(webster; wikipedia),并将“source”缩写为“src”。

Git的全部内容都围绕着提交(commit)展开。当我们克隆一个仓库时,我们的Git会连接到另一个Git。那个Git查找一个仓库,而那个仓库充满了提交。然后我们的Git在本地创建一个新的仓库,将所有提交传输到其中,并将所有分支名称转换为远程跟踪名称。然后我们的Git在这个新仓库中创建一个分支名称,基于他们的一个分支名称。至少,这是正常的过程。(如果你知道所有这些术语的含义,那太好了!如果不知道,现在也不用太担心。这里需要记住的是,我们得到了所有他们的提交没有他们的任何分支,然后我们通常让我们的Git创建一个与他们匹配的分支)。

由于Git的全部内容都围绕着提交,因此这个过程——复制所有他们的提交,但只复制一个他们的分支名称到我们自己的仓库中拼写相同的名称——就是我们所需要的。我们的Git重命名了所有他们的分支名称——因此除了一个例外,我们根本没有任何分支——通常并不是很重要。如果必要,我们自己的Git会稍后自动处理这个问题。

当我们使用git push时,我们正在请求我们的Git程序(它正在读取我们自己的Git仓库)连接到一些其他的Git程序——通常在运行服务器机器上——然后可以将数据写入其他的Git仓库。我们希望我们的Git向他们的Git发送我们的一些提交。特别是,我们想要发送我们的提交:我们刚刚创建的那些。毕竟,那里是我们放置所有好东西的地方。(Git的全部内容都围绕着提交展开,所以那是我们唯一能放置任何东西的地方。)

一旦我们发送了这些提交,我们需要让他们的Git将其中一个分支名称设置为“remember”我们的新提交。这是因为Git查找提交的方式是使用分支名称。每个提交的真实名称都是大而丑陋的哈希ID号码,没有人想要记住或查看;因此,我们使用分支名称让Git记住这些数字。这样,我们只需要查看分支名称,这些名称对我们来说可以有意义:trunk、feature/tall、tuatahi或其他名称。默认情况下和约定俗成的方法是使用git push进行操作,非常简单。
git push origin main

例如,git push部分是指发送提交并要求设置名称的命令。 origin部分是Git称为远程的内容:一个短名称,主要保存URL。这里结尾的main部分是我们的分支名称。那就是我们的Git用来查找我们的提交的分支。我们将让我们的Git发送我们的提交,然后要求他们的Git也设置他们的main
最后一部分-在这里放入main的部分-是Git称为refspec的内容。实际上,Refspecs允许我们放入由冒号或其他形式分隔的两个名称。例如,我们可以使用Arka's answer中的HEAD:main(尽管出于技术原因,在许多情况下,我们可能要使用HEAD:refs / heads / main)。但在简单情况下,我们只需使用一个分支名称:git push origin main。简单的分支名称是Refspec的简单形式。
为了使其工作,源名称必须是我们自己的Git存储库中现有分支的名称。这就是事情出错的地方。
(另请参见Message 'src refspec master does not match any' when pushing commits in Git

3Git可以使用任何名称,而不仅仅是分支名称。例如,标签名称也可以正常工作。但本答案关于分支名称,因为问题是关于分支名称的,并且在这里使用分支名称是最常见的。


如果我们的 Git 只创建了 master 分支会怎样?

假设我们正在使用 GitHub,并要求 GitHub 为我们创建一个新的存储库。他们运行了一种形式的 git init,将名称 main 作为新存储库的初始分支名称提供。他们可能也会创建一个提交。假设我们让他们创建这一个提交。那个提交将保存基于我们在 web 界面上选择的 README 和/或 LICENSE 文件。创建该初始提交实际上创建了分支名称 main

如果我们现在克隆他们的存储库,我们将获得他们的一个提交,该提交将位于他们的分支名称 main 下。我们的 Git 将重命名他们的 mainorigin/main,然后创建一个新的分支名称 main,以匹配他们的分支名称。所以一切都好。

但是,如果我们使用 git init 自己创建一个空的 Git 存储库,我们的 Git 可能会设置我们的第一个提交以创建名称为 master 的分支。我们将没有一个 main 分支:我们将有一个 master 分支。

或者,如果我们没有让 GitHub 创建一个初始的提交,那么 GitHub 存储库将完全为空。因为它没有提交,所以它也没有分支:只有指定了某个提交的分支名称才被允许存在。因此,如果我们克隆这个空存储库,我们也将没有分支,我们的 Git 将不知道使用 main,我们的 Git 可能会使用 master。我们回到了同样的情况,即我们的 Git 认为应该创建的第一个名称是 master

因此,在这些不同的情况下,我们进行第一次提交,并且所有提交都在名为 master 的分支上。如果我们现在运行:

git push -u origin main

(无论是否使用-u参数;我不会在这里详细讲解-u的内容)我们的Git在Git仓库中寻找名为main的分支。但是它不存在!因此,我们的Git只会给我们这个提示:{{提示信息}}。
error: src refspec main does not match any

错误信息。
为了解决这个问题,我们可以使用 git push origin master 命令——它会发送我们的提交并请求 GitHub 在其仓库中创建一个名为 master 的新分支;或者我们可以将我们的 master 重命名为任何我们想要的名称,然后使用该名称。
git branch -m master xyzzy
git push -u origin xyzzy

我們將使用的(單一)分支名稱更改為xyzzy。如果您想在這裡使用main,請將您的master重命名為main

如果您不小心創建了兩個分支怎麼辦?

假設我們使用GitHub創建了一個新存儲庫,其中包含一個初始提交,其中包括通常的README和LICENSE文件,使用他們的新默認分支名稱main。然後,在沒有考慮的情況下,我們在自己的計算機上使用git init創建了自己的新存儲庫,其預設分支名稱為master,並在master上進行了一兩次提交。
如果我們現在將master重命名為main
git branch -m master main

然后尝试推送:

git push -u origin main

我们得到一个不同的错误:

 ! [rejected]        main -> main (non-fast-forward)

这是因为很简单:他们有一个提交,使用他们的名称“main”,我们没有。如果他们更改他们的名称“main”以查找我们发送给他们的最后一次提交,他们将失去他们所做的初始提交,其中包含README和LICENSE文件。
你有几个选择:
- 你可以忽略他们所做的初始提交。毕竟,它只是一个样板提交。你可以告诉他们完全放弃它。按照任何现有的StackOverflow答案中概述的使用git push --force。 - 你可以获取他们的初始提交并在这些提交上进行rebase。这可能有点棘手,因为你的第一个提交是根提交。如果你的第一个提交包含README和/或LICENSE文件,则会出现add/add冲突。在这种情况下,强制推送可能更简单。 - 你可以获取他们的初始提交并合并你的提交。在现代Git中,这需要使用--allow-unrelated-histories选项。与rebase方法一样,如果您的提交包含README和/或LICENSE文件,则会出现add/add冲突。生成的存储库还将具有两个根提交。这些都不是严重的问题,但可能会稍微有点烦人。
要获取他们的提交,只需运行git fetch origin。这将获取GitHub的第一个提交,并在你自己的Git存储库中使用名称origin/main来记住它。然后你可以:
git rebase origin/main

或者:

git merge --allow-unrelated-histories origin/main

为了实现变基或合并,您可以选择在任何时候在此之前或之后将分支重命名为main


4
首先,感谢你详细的解释,我没有预料到会得到这样水平的信息。我还有一个请求,请指点我一些博客,让我能够理解关于rebase和root commit的知识。 - Arka
关于博客文章我不是很确定,但是在StackOverflow上有很多关于变基、根提交等方面的答案,例如:如何使用Git更改项目的第一个提交?如何在git交互式变基中将提交合并到下一个提交中?。然而,这个问题和答案可能更加直接相关:如何在Git中在根提交之前插入一个非空提交? - torek
请注意,您可以使用StackOverflow上的搜索栏搜索StackOverflow:在方括号内字面上输入[git],然后输入各种关键字,SO将使用原始问题上带有[tag:git]标签的这些关键字搜索他们自己的问题和答案。 - torek
哇,这是一篇文章! - Rafo
非常棒的答案。在我的情况下,解决“错误:src refspec main does not match any”错误的方法甚至更简单 - 我还没有提交任何内容,所以运行git commit -m“Initial commit”就为我解决了这个问题。我在这里添加这个步骤,以防其他人像我一样忽略了这个简单的步骤。 - Brady
这个回答的详细程度非常高,做得很好。我已经使用 Git 多年了,但正如你所指出的,我们本地的工具通常会“隐藏”一些细节。如果可以的话,我会给你多个赞。 - rockhowse

47

我几个小时前遇到了一个类似的问题,但最终找出了错误原因和解决方法。

我的做法:

  • 在GitHub上创建了一个git仓库

  • 在我的代码编辑器(VS Code)中将项目初始化为git仓库

  • 使用以下命令将URL添加到我的仓库中:

    git remote add origin https://github.com/xxxxxx/xxxxx.git
    

这时候

git remote -v 

可能会如预期一样给出

origin  https://github.com/xxxx/xxxx.git (fetch)
origin  https://github.com/xxxx/xxxx.git (push)

请注意

git branch 

目前你还没有创建任何分支,因此此时不会显示任何内容,而且你也无法创建任何分支。

问题:

我尝试过...

git push -u origin main

我收到了

error: src refspec main does not match any
error: failed to push some refs to 'github.com:xxxx/xxxx.git'

即使使用Git推荐的命令

git push --set-upstream origin master (or main preferably) 

我遇到了同样的错误。

现在提供解决方案:

在你的项目中添加一个文件,例如README.md。

git add .
git commit -m "added README.md"
git branch -M main   

-M用于重命名你的分支,如果你不想把它称为master。

最后,

git push origin main

谢谢!这解决了我整个问题。 - aelkz
最小的努力,最大的满足!这是一个相当奇怪的问题,以前从未遇到过这样的问题,但是您提供的解决方案非常棒 :) 谢谢。 - Benji
git remote -v 解决了我的问题。谢谢。 - undefined

9

您可以使用以下方法:

git add . 

如果已经完成,请尝试提交:
git commit -m "First commit for example..."
git branch -M main   

最后:
git push origin main

1
这个答案应该放在更上面,因为忘记提交也会导致问题。 - micsthepick

8

在进一步研究后没有结果,我试了个小技巧。下面是方法。

执行 git push -f origin HEAD:main 后,我完全删除了本地项目文件夹,然后从主分支克隆了我的项目。现在我可以使用 git push origin main 推送任何想要的更改。我检查过,现在在项目的 .git/refs/heads 位置有一个 main 文件。


1
这是唯一对我起作用的解决方案。似乎 -f 是神奇的覆盖标志,可以强制 git 执行您想要执行的操作。 - IgorGanapolsky

5

如果这是您第一次推送到主分支,请在提交更改后按照以下步骤操作。我遇到了这个错误:

src refspec main does not match any
error: failed to push some refs to 'https://github.com/<my_project_name>.git

我在提交后使用以下步骤进行修复。更改以下代码中您的Github网址:

git branch -M main
git remote add origin https://github.com/Sidrah-Madiha/<my_project_url>.git
git push -u origin main

我收到一个错误:![rejected] main -> refs/heads/main(已存在) - IgorGanapolsky
1
请查看此链接 https://dev59.com/VWEh5IYBdhLWcg3wPhdT,似乎您正在使用 git branch main 而不是 git branch -M main - Sidrah Madiha Siddiqui
但现在我遇到一个错误:致命错误:远程源已经存在 - IgorGanapolsky
1
我已经成功重现了你的问题,请确保你使用了 git add . 或者在命令中添加你想要提交的文件,然后使用 git commit -m "你的提交信息",接着使用上面所有的命令从 git branch -M main 开始执行。如果这样可以解决你的问题,请告诉我。 - Sidrah Madiha Siddiqui
1
我使用强制-f标志进行推送,解决了我的问题。这是唯一有效的方法。 - IgorGanapolsky

2
在我的情况下,我只是试图推送一个空文件夹。 添加了test.txt文件,一切正常运行!
这是我使用的内容:
cd existing_folder
git init --initial-branch=main
git remote add origin https://.../repo.git
git add .
git commit -m "Initial commit"
git push -u origin main

1
对我来说,将以下内容添加到~/.ssh/config文件中有效。
Host github.com
  Hostname github.com
  User <your username>
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519

注意:在我的 GitHub 授权的 SSH 密钥中添加了 id_ed25519.pub

0

有时候你可能会从主分支克隆你的仓库,现在你想将其提交到主要分支。如果你的本地仓库在主分支上,而你正在尝试将其提交到远程仓库的主要分支,则可以尝试使用以下命令。

git push -f origin master:main


0
我遇到了同样的问题,但是这个命令解决了问题:
git branch -M main

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接