将文件和更改从一个分支移动到另一个分支

时间:2020-09-21 18:06:37

标签: git repository git-branch git-checkout

我对git很陌生。但目前,我在master下有两个分支:

refactorfinal。我试图将所有文件从refactor移入final,但是在检出到refactor并重新设置到final后,我得到了最后一个错误:

fatal: Needed a single revision
invalid upstream final

基本上,我正在尝试在refactor中处理我的代码,并在进行测试以将其推送到主代码之后。

我该怎么做?

1 个答案:

答案 0 :(得分:2)

从头开始并向后工作-顺便说一句,Git也是这样做的-让我们看一下:

无效的上游决赛

这表明您运行了git rebase final,但还没有分支名称final

我正在尝试将所有文​​件从refactor移动到final

从这里开始,有几件重要的事情要知道:Git与文件无关。我们待会儿再说,现在回退一下:

但是目前,我在master下有两个分支...

分支-更确切地说,分支名称-没有任何上/下关系。 (这种向后移动的东西有点痛苦,不是吗?但这是Git所做的,因此,做一会儿是一个很好的练习。?)

现在,这里要了解的有关Git的事情就是有关 commits 的全部内容。它与文件或分支无关。文件和分支当然很重要,但是就 Git 而言,重要的是提交。提交保存文件,我们使用分支名称​​ 找到一个提交。但是Git只是关于提交。然后,您可能想做的就是移动提交,但这也可能是一个问题。这是您需要知道的。

Git就是关于提交的

由于Git是关于提交的,因此您需要确切地知道什么是提交并为您做什么。因此,您必须记住一些事情:

  • 每个提交都有编号。他们不计算数字,例如1、2、3;但是每个提交都有一个唯一的编号。数字看起来是随机的,而且又大又丑,并且里面也有字母:例如385c171a018f2747b329bcfa6be8eda1709e5abd。这些数字实际上是提交中所有内容的加密校验和。 Git通过该编号查找提交。

  • 每个提交都包含两个部分,即 data metadata:

    • 提交中的数据只是Git在您(或任何人)进行提交时知道的每个文件的快照。这些文件以特殊的,只读的,仅Git的,压缩和重复数据删除的形式存储。重复数据删除处理了一个事实,即大多数提交大多只是重复使用上一次提交中的所有文件。

    • 提交中的元数据包含诸如您的姓名和电子邮件地址之类的内容,以及您想放入的任何日志消息。尽管如此,Git还是在此元数据中添加了自己的内容:每个提交都存储了提交编号,即哈希ID-上一个提交的ID。 Git将此称为提交的父级

Git中的其他大部分内容都来自以下事实:

  • Git不存储更改,而是存储快照。

  • 这些提交被串在一起,形成了向后看的链:

     ... <-F <-G <-H
    

    此处H是链中最后个提交的哈希ID。如果我们知道提交H的实际哈希ID,则可以让Git查找它。这将同时获取快照及其父提交G的实际哈希ID。我们可以让Git进行查找,以获取更早的快照,以及更早提交F的哈希ID,等等。

  • 由于提交的 number 是密码校验和,因此实际上无法更改任何有关提交的内容。如果您取出一个并对其进行一些更改并存储结果,则会得到具有不同哈希ID的 new和different 提交。旧的提交仍然存在,没有变化。

  • 分支名称仅保存链中 last 提交的哈希ID。

  • 当您进行新的提交时,Git将 new 提交的ID写入名称:

     ...--F--G--H--I   <-- master
    

    在这里,我们向I添加了新的提交master。现有提交没有更改:H仍指向G,后者仍指向F,依此类推。我们所做的就是添加一个新的提交I,该提交指向H。当我们这样做时,由于我们正在使用master,因此Git将I的ID写入名称 master

所以名称可以移动,但是提交完全不变。

现在我们准备看一下“移动提交”

使用Git时,通常以git checkout branch开始。这会将文件从一个提交中复制出来(请记住,分支名称指定了一个提交,并且提交内部的文件采用只读,仅Git的形式)至可以使用它们的位置。它还告诉Git, name 是您当前的 name ,因此特定的 commit 是您当前的 commit 。这些图纸就是这样:

...--G--H   <-- master (HEAD)

关于。特殊名称HEAD被附加到分支名称中,例如master。那是您当前的分支,指向的提交就是您的当前提交。

如果您现在创建一个新的分支名称,例如refactor,则会得到以下信息:

...--G--H   <-- master (HEAD), refactor

切换到名称refactor后,您将拥有:

...--G--H   <-- master, refactor (HEAD)

无论哪种方式,您仍在使用提交H。只是提交H名称masterrefactor

现在,您可以按照通常的方式进行新的提交。如果您在refactor上的话,会发生以下情况:

...--G--H   <-- master
         \
          I--J   <-- refactor (HEAD)

在这里,您进行了两次新提交。这些快照J是最后一个快照,包含文件和元数据。 J指向I,后者指向H名称 refactor选择提交J,名称master选择提交H

我[想]提交从存储库refactor到存储库final的所有更改

请稍等:您刚刚说过存储库,但是您之前说过了分支

存储库是提交的集合(带有分支名称,可以帮助您和Git 找到提交)。一个 branch 是...嗯,它是模棱两可的:人们用这个词来表达不同的意思。但是分支名称是可以帮助您和Git查找一个特定提交的名称,Git可以根据需要向后进行该操作。

如果您要使用新的拼写final分支名称来标识提交J,这很容易:

git branch final            # makes `final` point to the current commit

或:

git branch final refactor   # makes `final` point to the same commit as `refactor`

最终结果可能看起来像这样-请再次注意,实际上没有任何提交已更改:

...--G--H   <-- master
         \
          I--J   <-- refactor (HEAD), final

Git以非常混乱的方式使用单词

Git有很多技术术语,例如 remote 存储库分支,等等。并非每个人实际上都以正确的方式使用了这些术语(其中有些一开始并不是很好,有些已经随着时间而发展)。如果您试图将问题传达给人类,或者让Git做某事,那么使用正确的术语或在不确定术语时添加一些解释可能非常重要。 / p>

Git有一个glossary可以在这里提供帮助。绝对不是完美的,但这至少是一个起点。