没有可比性。没有可比性,分支的提交历史完全不同。

187

我在我的电脑上安装了一个CMS主题。我通过git跟踪它的更改,并决定将其备份到GitHub上,以便分享这些更改。

该主题也可以在GitHub上获得。在我的电脑上,我已经将其添加为远程上游。现在,我可以使用以下命令轻松地查看我的主分支和远程上游之间的更改:

git diff --color master upstream/number
如果我能在GitHub上添加远程上游,我就可以轻松地分享这些更改。在GitHub上设置这种关系可能吗?
我已经尝试过以下操作:
git push -u origin upstreambranch

在 GitHub 上将 upstreambranch 添加到主分支。但是尝试比较这两个分支并不起作用,在 GitHub 上得到的结果是:"没有可比较的内容"。

有没有其他方法可以比较这些分支?


我正在使用一个名为Omeka的CMS和一个名为Seasons的特定主题。我已经修改了这个主题并将其上传到以下位置: https://github.com/padraic7a/seasons我想要一种可视化的方式(差异)来向人们展示它与“原始”版本的不同之处。我尝试通过下载并将此版本推送到GitHub来实现这一点: https://github.com/padraic7a/seasons/tree/upstreambranch在上面的帖子中,我解释了我是如何做到这一点的,但它没有起作用。这样更清楚吗? - Jack
我找出了您当前的问题所在,但是从更大的角度来看,您可能需要重新考虑您现在正在做的一切,正如我在之前的评论中提到的一样,但这取决于您最终想要做什么。针对您当前的问题编写答案... - user456814
我明白你的意思,这确实是一个我从一个糟糕的起点开始的情况。 - Jack
我在使用git子树时遇到了问题。我使用了git subtree split命令来提取子树中所做的更改,将分支推送到原始子树所在的远程仓库,但现在我无法将更改合并到该仓库中任何现有的分支中。不确定如何继续操作。 - yoyo
在我的情况下,我所需要做的就是点击“交换修订版本”按钮。或许值得一试。 - Raphael
显示剩余4条评论
26个回答

241

如果问题是"主分支和开发分支有完全不同的提交历史记录",则以下方法可行:

git checkout master   
git branch main master -f    
git checkout main  
git push origin main -f 

2
这个代码解决了我的问题,我不知道发生了什么,但我之前无法在Github上发起拉取请求。 - Lance2k
1
一样。对我有用。只是为了澄清给其他像我这样的新手。将“origin”替换为您的存储库名称。 - Daniel Melendrez
4
是的,它有效,非常感谢。使用此功能的人请不要忘记备份更改,否则您将会丢失它们! - codergirrl
3
如果您能添加一些位的解释,那就太好了,除此之外,这个程序运行得非常好。 - Pardeep Jain
10
这刚刚删除了我在主分支中的文件,并将所有内容从主分支推送到主分支,教训是要备份。 - ozkanpakdil
显示剩余4条评论

126

简短回答

看起来 GitHub 不允许你比较分支,因为它们实际上根本没有共享任何相同的历史记录,即使它们可能共享许多相同的文件和代码。

这是我制作的临时 fork 仓库的屏幕截图,我尝试比较 masterupstreambranch,就像你描述的那样。请注意错误消息:

Error message screenshot

它说:

没有任何可以比较的东西。

masterupstreambranch 是完全不同的提交历史。

长答案

你可能是下载了原始源代码并将其添加到一个全新的仓库中,而不是克隆原始仓库,对吧?这样做会使你的仓库历史记录与原始仓库的历史记录完全不同,因为你的新仓库不会有任何相同的提交和相同的 sha ID。

你可以通过反向日志查看你的 master 分支和 upstreambranch 的差异:

# Your first commit, see commit sha
git log --reverse master
commit c548d7b1b16b0350d7fbdb3ff1cfedcb38051397 # <== HERE
Author: Padraic Stack <padraic.stack@nuim.ie>
Date:   Wed Apr 2 15:11:28 2014 +0100

    First commit of everything

# First commit sha of the original repo
git log --reverse upstreambranch
commit 105a12817234033c45b4dc7522ff3103f473a862 # <== THERE
Author: Jeremy Boggs <jeremy@clioweb.org>
Date:   Mon Feb 22 16:00:53 2010 +0000

    Creates repo directories for the Seasons theme.

解决方案

如果你重新提交并覆盖原有的记录,你应该能够比较这些分支。你可以通过多种不同的方法来重新提交你的记录,包括

git rebase --onto

并且

git cherry-pick

如果需要的话,您也可以手动重新提交每个提交。


1
谢谢您花费时间,我很感激您所付出的努力。您的回答让我知道我尝试做的事情是不可能的,所以我接受了它。只是为了明确一下,当我说“但是尝试比较这两个分支时无法工作,GitHub 上得到的结果是:“没有要比较的内容””时,我已经提到了错误。 - Jack
12
@Jack 欢迎您。是的,您提到了这点,但您遗漏了错误信息的其余部分,即“主分支和上游分支是完全不同的历史记录。” 这是问题的关键所在。 - user456814
11
git rebase -i origin/master 这对我很有效。在执行此操作后,我能够比较两个分支。 - sujay
1
@sujay 这是正确的。在这样做之后,我可以进行比较。 - Raja Simon
1
短答案是默认的SO答案格式。长答案则是: - lys
显示剩余3条评论

103

我曾经遇到过类似的情况,我的主分支和我想要合并的开发分支有不同的提交历史记录。以上解决方案都对我没有用。最终解决方法是:

从主分支开始:

git branch new_branch
git checkout new_branch
git merge develop --allow-unrelated-histories

现在在新分支中,有来自 develop 的所有内容,我可以轻松地合并到主分支中,或者创建一个拉取请求,因为它们现在共享相同的提交历史。


13
简洁而实用。谢谢。 - Peter Mghendi
9
前两个命令可以简化为 git checkout -b new_branch。这将在 master 分支的基础上创建一个名为 new_branch 的新分支并切换到它。 - theyCallMeJun
4
这对我来说没有用,但感谢您帮助了其他人。我会继续寻找。 - ASH
2
太棒了...! - Karolina Hagegård
1
最佳答案,谢谢。 - Daniel Miradakis

69

我使用以下命令解决了我的问题

git checkout [BRANCH]   
git branch master [BRANCH] -f   
git checkout master   
git push origin master -f

8
这将使得[BRANCH]的更改在主分支中可用,您将无法创建拉取请求。 - Tejas Garde
1
@Susie是“强制”的缩写! - iamgraeme
21
将新的“主”分支设为默认分支,可以按以下方式操作:`git checkout master
git branch main master -f
git checkout maingit push origin main -f `
- Henrique Bruno
1
我已经采用了您提出的解决方案,现在我的旧分支已经被删除,我也无法访问任何之前的提交记录。谢谢! - MercifulSory
工作得很顺利,伙计。 - undefined
显示剩余4条评论

43

您可以按以下方式强制更新您的master分支:

git checkout upstreambranch  
git branch master upstreambranch -f    
git checkout master  
git push origin master -f

如果你在将代码合并到GitHub的新默认分支main时遇到问题,可以使用以下方法:


git checkout master  
git branch main master -f    
git checkout main  
git push origin main -f

以下命令将强制两个分支具有相同的历史记录:
git branch [Branch1] [Branch2] -f 

3
逐行解释对初学者很有帮助。其中一些命令可能具有潜在危险。 - Ribena
1
我不是一个精通Git的超级酷的人,能否请@blue给我解释一下? - Kuldeep Kumar
@TaslimOseni 很高兴能够帮助。 - blueware

23

从实验分支

git rebase master
git push -f origin <experiment-branch>

这将创建一个共同的提交历史记录,以便比较这两个分支。


8

这似乎是 GitHub 的不良行为,但很容易解决。您需要做的是将您的分支基于现有历史记录中的一个合理(任何合理的)提交进行变基。您可以执行以下操作:获取 GitHub 存储库并找到其历史记录中与您起始点最相似的树。请按照以下方式开始:

git remote add github u://r/l
git fetch github

myroot=`git rev-list master --max-parents=0`
root_tree=`git rev-parse $myroot^{tree}`

github_base=`git log --pretty=%H\ %T github/master | sed -n "s/$root_tree//p"`

希望你能幸运地在Github历史记录中找到与你开始的完全相同的代码树。假设成功了,

git rebase --onto $github_base $myroot master 

完成。


如果找不到匹配的树,则需要找到最接近的近似值。以下是一种获取差异粗略估计的方法:

git log --pretty='echo %H $(git diff-tree -p -b -U0 '$myroot:' %T|wc -l)' github/master \
| sh

这将计算github/master历史中每个提交的树之间最小化差异中的行数,并与您的根树进行比较。希望能获得一个不错的小差异,您可以在调用github_base提交并进行上述变基之前查看实际差异。



7
如果你在2023年在这里,请做这个。
 git checkout [BRANCH]   
 git branch main [BRANCH] -f   
 git checkout main
 git push origin main -f

6

术语

首先,让我们弄清楚一些术语...

upstream <= 远程 git 仓库(通常是生产环境中主分支或发行版分支所在的仓库)

forked-repo <= 远程 [实验性 git 仓库] (https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) ,也称为“origin”。

local repo <= 您在本地工作站上使用的文件和目录,您可能通过运行 git clone my-forked-repo.git 命令获取了这些文件。

local index <= 也称为本地 git “stage”,即您将文件推送到远程仓库之前的暂存区。

Github 工作流程

接下来,让我们谈谈将更改提交到 upstream 仓库的过程:

通常的过程是在功能分支上工作,然后将该分支推送并打开一个 Pull Request,将其合并到 forked-repo 的master分支或 upstream 的master分支中。

通过运行git checkout -b FEATURE_BRANCH_NAME创建一个功能分支。

添加/删除/修改项目文件。

通过运行git add . 添加文件。

通过运行git commit -m'My commit message' 将您的文件提交到暂存区。

通过运行git push origin FEATURE_BRANCH_NAME 推送您的暂存区文件。

完全不同的提交历史记录的解决方案

当您 fork 了一个 git 仓库并更改了 git 历史记录时,可能会出现“master 和 upstreambranch 是完全不同的提交历史记录”的消息。

例如,如果你 fork 了一个仓库并将其拉到本地进行工作...

如果然后您决定重写整个应用程序,并决定删除所有现有文件,包括 forked-repo 的 .git 目录。您添加新文件和目录来重新创建应用程序,并使用 git init 命令重新创建 .git 目录。

现在,您的应用程序使用新文件运行良好,您想将其合并到 upstream 仓库中。但是,当您推送更改时,您会收到“...完全不同的提交历史记录...”错误消息。

你会发现你在新的本地目录和远程分支(my-forked-repo)上原始的git提交记录是不同的。可以通过在当前目录运行以下命令来检查:git log --reverse master,然后运行以下命令:pushd $(mktemp -d); git clone https://github.com/my-forking-username/my-forked-repo.git; git log --reverse master; popd
如果你想提交你的更改并进行拉取请求(以期将你的新更新合并到upstream/master分支),则必须修复本地.git仓库,使其与远程的my-forked-repo相匹配。
git clone https://github.com/my-forking-username/my-forked-repo.git
cd my-forked-repo
git checkout -b my-new-files-branch-name
# Delete all files and directories except for the .git directory
git add .
git commit -m'Remove old files'
# Copy your new files to this my-forked-repo directory
git add .
git commit -m'Add new files'
git push origin my-new-files-branch-name

在 GitHub 上创建一个 PR,请求将您的 my-new-files-branch-name 分支合并到 master 中的 my-forked-repo 中。
注:对于相同原因,非 forked 的 repo 也可能出现“完全不同的提交历史记录”错误消息,并且可以使用上述相同的解决方案进行修复。

5
当我尝试使用README文件初始化GitHub存储库并将现有的本地git存储库推送到其中时,出现了以下错误。这导致一个默认分支为README文件的main分支,以及一个包含代码的master分支,它们无法合并。
但是,由于我的main分支实际上没有任何重要内容(如果您需要保存两个分支的数据,请查看PaianuVlad23的答案),我通过将默认分支更改为master分支,然后删除main分支来解决了问题,步骤如下:
  1. 在GitHub中,单击窗口右上角的用户图标。
  2. 选择“您的存储库”,然后单击存储库名称。
  3. 在存储库名称下方,选择“设置”选项卡。
  4. 从左侧窗格中选择“分支”选项。
  5. 在“默认”标题下,将默认分支从要删除的分支(在我的情况下为main)更改为要保留的分支(在我的情况下为master)。
  6. 现在,单击存储库名称下的“Code”选项卡。
  7. 在包含“Code”等的选项卡行下方,您将看到一个标识为“2 branches”的位置。单击它。
  8. 找到要删除的分支,并在该行右侧单击垃圾桶图标。
现在,您的存储库只有一个分支,即您想将本地更改推送到的分支!就像您在此线程中的@mfaani回答中建议的那样,在推送之前未初始化存储库一样。

1
如果您确定要删除不需要的分支,这是一个非常简单的解决方案。将“默认”切换到您想要保留的分支非常重要。完美地解决了问题。 - Andrea Antonangeli

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