android - 对本地主服务器进行更改后,我们应该使用推送或合并到远程主服务器吗?
问题描述
我从 git 克隆了一个 android 项目,并创建了一个名为devBranch
from的本地分支master
。
我做了很多改变,devBranch
我也远程推送了它。
现在,一旦我完成了所有更改,devBranch
我将这些更改合并到主本地分支。
现在我想将本地主机中的这些新更改推送到远程主机。
什么是合适的方法?我应该使用推送还是合并,为什么?
解决方案
比较git push
不是git merge
很明智:
该
git push
命令是关于向负责其他存储库的其他 Git 发送一些提交,以便其他存储库获得新的提交,然后要求其他 Git 调整某些分支和/或其他名称在另一个存储库中。该
git merge
命令很复杂,但以其中一种典型方式使用时,就是在您自己的存储库的当前分支中进行新的提交。这个新的提交通常是一个合并提交,有两个父级,而不是更常见的一个父级的普通提交。
现在,有些情况下git merge
不会进行新的提交,而是执行快进操作。快进操作是分支名称的更改,以便存储在该名称中的新提交哈希 ID 标识其哈希 ID 先前存储在该名称中的提交的后代。(这是一个非常专业的术语,需要一些图论才能理解。请参见下面的简单示例。)
该git push
命令还可用于不发送新提交,但仍请求其他 Git 存储库对其分支名称之一进行更改。无论您的 Git 是否发送任何新提交,此更改都可以是一个快进操作。实际上,如果分支名称更改是非快进操作,则该git push
命令需要--force
or--force-with-lease
选项。
既然两者都git merge
可以git push
进行这种快进动作,那么至少有一种情况,两者有几分可比性。但是,这种特殊情况的主要区别在于,git merge
它在您的存储库中git push
执行快进,而在其他Git 存储库中执行快进。
可以说,底线很简单:
- 如果您需要进行合并提交,则必须在本地进行。该
git push
命令不能这样做。 - 如果您不需要进行合并提交,请问问自己谁的分支名称需要什么样的更新。要更新您自己的分支名称,请在本地工作。要更新其他一些 Git 存储库,请使用
git push
.
请记住,存储库共享提交(通过哈希 ID),但有自己的私有分支名称。你的名字不是其他任何人的名字,也不需要以同样的方式使用——但人类是人类,我们倾向于以同样的方式使用相同的名字,因为如果我称你为 Fred 而你的同事称你,那就太混乱了Piotr 当你的名字实际上是 Rahul。
画出快进意味着什么
为了理解 Git 的快进概念,让我们从分支名称保存提交哈希 ID 的事实开始,提交也保存提交哈希 ID。每当某事物拥有提交哈希 ID 时,我们就说该事物(无论它是什么)指向该提交。所以一个提交指向另一个提交,一个分支名称指向一个提交。
任何给定提交的实际名称都是一些丑陋的散列 ID,faefdd61ec7c7f6f3c8c9907891465ac9a2a1475
例如。这些输入起来太烦人了,人类也很难记住,所以让我们用大写字母来绘制我们自己的 Git 提交图片段来代替每个提交。在这里,我们连续提交了三个提交,最后一个(最新的)提交是 commit H
:
... <-F <-G <-H
由于H
是最新的提交,我们将有一个分支名称指向它:
... <-F <-G <-H <--master
同时,提交H
本身实际上存储了早期提交的原始(和真实)哈希 ID G
。所以H
指向G
. CommitG
反过来将之前提交的哈希 ID 存储在其中F
:G
指向F
. 这就是我们在这里绘制的。
任何提交的任何部分,一旦完成,就无法更改。这意味着我们实际上不必将提交之间的内部、向后指向的箭头绘制为箭头:我们可以将它们绘制为连接线。当我们开始添加更多的提交时,这很有用H
,使用另一个名称来查找它们:
...--F--G--H <-- master
\
I--J <-- dev
在这里,分支名称dev
指向 commit J
,向后指向 commit I
,向后指向 commit H
,依此类推。同时,名称 master
仍然指向现有的 commit H
。
我们现在可以让 Git “master
向前滑动名称”。如果我们只进行一次提交,master
最终会指向I
,如下所示:
...--F--G--H--I <-- master
\
J <-- dev
请注意提交没有改变:我们刚刚将提交画I
高了一行,因为没有其他好的方法可以在 StackOverflow 上绘制它们。名称发生了变化,或者更准确地说,存储在名称中的值发生了master
变化,因此master
现在指向I
.
如果我们master
一直向前滑动,我们会得到:
...--F--G--H
\
I--J <-- dev, master
现在根本没有理由继续纠结:
...--H--I--J <-- dev, master
就够了。
这个操作——移动主“向前”一个或多个提交——是 Git 所说的快进,因为即使master
now 指向I
or J
,我们也可以通过从我们现在通过该名称找到的任何提交开始,向后工作到 wheremaster
是以前。它在commit 处H
,并J
指向I
which 指向H
. 所以 commitH
保留在名为master
.
但是如果我们从这个开始:
...--F--G <-- master
然后添加一个新名称dev
也指向现有提交G
:
...--F--G <-- dev, master
然后进行一个新的提交master
,使它指向这个新的提交H
,然后检查分支dev
并进行一个新的提交,dev
这样它就指向dev
了新的提交I
?我们现在将拥有:
H <-- master
/
...--F--G
\
I <-- dev
从master
(位于 commit 的位置H
),我们可以返回到 commit G
,然后是 commit F
,依此类推。从——dev
提交I
——我们也可以返回到G
等等F
。但是这些连接提交的箭头完全是向后的箭头。我们不能从G
到“前进” H
。Git 的连接只指向backs。在我们返回之前,我们需要名称master
以便找到 commit 。H
如果我们强制 Git 将名称移动master
到 commit I
,我们最终会得到:
H ???
/
...--F--G
\
I <-- dev, master
提交仍然存在,但我们无法找到它的哈希 ID 。提交H
丢失:它仍然存在(一段时间),但除非我们强制 Git 合理地快速恢复它,否则 Git 最终会完全删除它,因为它是不必要的。1 这种提交H
丢失的强制名称运动是非快进的。
如果我们想加入提交H
并I
保持两者的工作完成,我们将需要使用git merge
(或类似的东西)。
1在正常的存储库中,Git 留下的痕迹可以让我们至少再恢复 30 天的提交。在服务器上的裸存储库中,恢复时间要短得多。
推荐阅读
- java - Spring 如何从返回 CompletableFuture 对象的端点获取结果?
- powershell - PowerShell 2 等效于 Enable-NetAdapterBinding
- node.js - 拦截任何 http.IncomingMessage 并打印正文
- jquery - Bootstrap 模态数据刷新
- php - 为什么身份验证令牌不与 CURL 一起显示?
- apache-spark-sql - pyspark to_timestamp() 返回空值
- xpath - 导入到 Google 表格第一次/第二次/第三次出现在网站上的课程
- android - 自定义搜索栏
- python - 在熊猫数据框中搜索字符串
- azure - 构建、分析和崩溃报告 - 应用中心或 Azure