Git基础知识¶
Git是一个与其他开发人员交换提交(文件更改)和分支(提交组织)的工具。
作为一个分布式修订控制系统,Git没有中央服务器的概念。然而,对于Sage开发,Git通过以下方式与其他开发人员通信 the Sage repository 在GitHub上。因此,我们假设在本指南中。
通过SSH进行Git身份验证¶
为了将更改安全地推送到远程存储库,Git使用了公钥加密技术。本节将向您展示如何设置必要的加密密钥,以便在您希望使用SSH(安全Shell)协议而不是HTTPS协议向GitHub验证您的Git的情况下。
生成SSH密钥¶
检查您是否已经拥有合适的SSH密钥 .ssh
主目录中的目录。如果您还没有合适的SSH密钥,可以使用 ssh-keygen
工具。
遵循其中之一 the detailed instructions 或以下简短说明:
[alice@localhost ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/alice/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/alice/.ssh/id_rsa.
Your public key has been saved in /home/alice/.ssh/id_rsa.pub.
The key fingerprint is:
ce:32:b3:de:38:56:80:c9:11:f0:b3:88:f2:1c:89:0a alice@localhost
The key's randomart image is:
+--[ RSA 2048]----+
| .... |
| .. |
| .o+ |
| o o+o. |
|E + . .S |
|+o . o. |
|. o +.o |
| oB |
| o+.. |
+-----------------+
这将在 .ssh
您的主目录中的文件夹。默认情况下,它们是
~/.ssh/id_rsa
你的私钥。注意安全。 Never 把它分发给任何人。
~/.ssh/id_rsa.pub
对应的公钥。此文件且仅此文件可安全地泄露给第三方。
这个 ssh-keygen
工具将允许您使用不同的文件名生成密钥,或使用密码短语保护它。根据您对自己的计算机或系统管理员的信任程度,您可以将密码保留为空,以便能够在没有任何人工干预的情况下登录。
将用于身份验证的公钥添加到GitHub¶
请遵循以下程序 Adding a new SSH key to your GitHub account 。然后检查它是否通过以下方式工作:
[alice@localhost sage]$ git remote add origin git@github.com:alice/sage.git
[alice@localhost sage]$ git remote -v
origin git@github.com:alice/sage.git (fetch)
origin git@github.com:alice/sage.git (push)
将更改推送到遥控器¶
将您的分支机构推向遥控器 origin
使用以下任一选项::
[alice@localhost sage]$ git push --set-upstream origin HEAD:my_branch
或:
[alice@localhost sage]$ git push origin HEAD:my_branch
如果您的分支机构已有上游分支机构。这里的“上游”指的是遥控器 origin
,这是 upstream 到你当地的Git回收站。
这里, HEAD
意味着您正在将当前本地分支的最新提交(以及它的所有父提交)推送到远程分支。
查看公关¶
如果您要处理PR分支的更改,则必须创建该分支的本地副本。特别是,Git没有直接使用远程分支的概念,远程只是您可以从/到远程服务器获取的东西的书签。因此,您应该做的第一件事是将分支中的所有内容放入您的本地存储库中。这是通过以下方式实现的:
[alice@localhost sage]$ git fetch upstream pull/12345/head
remote: Enumerating objects: 12, done.
remote: Counting objects: 100% (12/12), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 12 (delta 9), reused 11 (delta 9), pack-reused 0
Unpacking objects: 100% (12/12), 2.22 KiB | 206.00 KiB/s, done.
From https://github.com/sagemath/sage
* branch refs/pull/12345/head -> FETCH_HEAD
这个 pull/12345/head
分支指的是远程的PR#12345的分支 upstream
。现在,分支暂时(直到您获取其他内容)以别名存储在本地Git数据库中 FETCH_HEAD
。在第二步中,我们将其作为新的本地分支机构提供并切换到它。您当地的分支机构可以有不同的名称,例如::
[alice@localhost sage]$ git checkout -b my_branch FETCH_HEAD
Switched to a new branch 'my_branch'
在本地Git存储库中创建一个名为 my_branch
并将本地Sage文件系统树修改为分支中文件的状态。现在,您可以编辑文件并将更改提交到本地分支。
从遥控器获取更改¶
开发过程中的一个常见任务是将分支的本地副本与GitHub Sage Repo上的分支同步。特别是,假设你下载了别人的公关分支,比如Bob,并对公关的改进提出了一些建议。现在Bob将您的建议合并到他的分支中,您希望获得添加的更改以完成审查。假设您最初拥有本地分支机构,如 查看公关 ,您只需发出::
[bob@localhost sage]$ git pull upstream pull/12345/head
From https://github.com/sagemath/sage
* branch refs/pull/35608/head -> FETCH_HEAD
Merge made by the 'ort' strategy.
src/doc/common/python3.inv | Bin 98082 -> 131309 bytes
src/doc/common/update-python-inv.sh | 7 ++++---
2 files changed, 4 insertions(+), 3 deletions(-)
此命令从PR的分支下载更改并将它们合并到您的本地分支。
更新开发人员¶
这个 develop
分支可以像任何其他分支一样进行更新。但是,您的开发分支的本地副本应该保留 identical 至GitHub Sage Repo开发分支。
如果您意外地将提交添加到您的 develop
,则必须在更新分支之前将其删除。
确保将潜在问题通知给您的一种方法是使用 git pull --ff-only
,这将在需要非平凡合并时引发错误::
[alice@localhost sage]$ git checkout develop
[alice@localhost sage]$ git pull --ff-only upstream develop
如果此拉入失败,则说明主分支的本地副本有问题。要切换到正确的Sage主分支,请使用::
[alice@localhost sage]$ git checkout develop
[alice@localhost sage]$ git reset --hard upstream/develop
合并和更改基数¶
有时,当您在Git分支上工作时,会发布新版本的Sage。
让我们假设你是从 my_branch
在提交时 B
。一段时间后,您的分支机构已提前提交 Z
,但您更新了 develop
(见 更新开发人员 ),现在您的Git历史如下所示(请参见 历史 ):
X---Y---Z my_branch
/
A---B---C---D develop
你应该如何应对这样的变化?原则上,有两种方式:
Rebase: 第一个解决方案是 replay 提交
X,Y,Z
在新的顶端develop
。这叫做 rebase ,并重写您当前的分支:git checkout my_branch git rebase -i develop
就提交图而言,这将导致:
X'--Y'--Z' my_branch / A---B---C---D develop
请注意,此操作将重写
my_branch
(见 重写历史 )。如果有人开始在您的提交上编写代码,这可能会导致问题X,Y,Z
。否则是安全的。Alternatively ,您可以更改基数
my_branch
正在更新中develop
同时(请参见 从遥控器获取更改 ):git checkout my_branch git pull -r develop
Merging 您的分支机构
develop
将在两者之上创建一个新的提交:git checkout my_branch git merge develop
结果是下面的提交图:
X---Y---Z---W my_branch / / A---B---C-------D develop
Pros: 您没有重写历史(请参见 重写历史 )。然后,可以轻松地将额外的提交推送到GIT存储库,并分发给您的合作者。
Cons: 它引入了一个额外的合并提交,如果您使用REBASE,它就不会存在。
Alternatively ,您可以合并
my_branch
正在更新中develop
同时(请参见 从遥控器获取更改 ):git checkout my_branch git pull develop
In case of doubt 使用合并,而不是重新设置基准。涉及的风险较小,在这种情况下,Rebase只对历史非常悠久的分支机构有用。
合并工具¶
仅使用Git即可轻松解决简单冲突(请参见 冲突解决 )
对于更复杂的课程,有一系列专门的课程可供选择。因为冲突标记包括最近的公共父级的散列,所以可以使用三向diff::
[alice@laptop]$ git mergetool
This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
meld opendiff kdiff3 [...] merge araxis bc3 codecompare emerge vimdiff
Merging:
fibonacci.py
Normal merge conflict for 'fibonacci.py':
{local}: modified file
{remote}: modified file
Hit return to start merge resolution tool (meld):
如果您没有最喜欢的合并工具,我们建议您尝试 meld (跨平台)。结果如以下屏幕截图所示。

中间的文件是最新的公共父文件;右边是Bob的版本,左边是Alice的冲突版本。单击箭头会将标记的更改移动到相邻窗格中的文件。
冲突解决¶
如果存在重叠编辑,则会发生合并冲突,这是分布式开发不可避免的后果。幸运的是,使用Git可以很容易地解决这些问题。作为一个假设的示例,请考虑以下代码片段:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
return fibonacci(i-1) * fibonacci(i-2)
这显然是错误的。两个开发人员,即Alice和Bob,决定修复它。Bob更正了种子值:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
if i > 1:
return fibonacci(i-1) * fibonacci(i-2)
return [0, 1][i]
并将这些更改转换为新的提交:
[bob@laptop sage]$ git add fibonacci.py
[bob@laptop sage]$ git commit -m 'return correct seed values'
他将自己的更改作为GitHub Sage repo的公关,并将其合并到 develop
布兰奇。他的 fibonacci
功能还不是很完美,但肯定比原来的要好。
与此同时,Alice将乘法改为加法,因为这是正确的递归公式:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
return fibonacci(i-1) + fibonacci(i-2)
并将她的分支机构与最新的 develop
从GitHub Sage回购中提取的分支::
[alice@home sage]$ git add fibonacci.py
[alice@home sage]$ git commit -m 'corrected recursion formula, must be + instead of *'
[alice@home sage]$ git fetch upstream develop:develop
[alice@home sage]$ git merge develop
...
CONFLICT (content): Merge conflict in fibonacci.py
Automatic merge failed; fix conflicts and then commit the result.
该文件现在如下所示:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
<<<<<<< HEAD
return fibonacci(i-1) + fibonacci(i-2)
=======
if i > 1:
return fibonacci(i-1) * fibonacci(i-2)
return [0, 1][i]
>>>>>>> 41675dfaedbfb89dcff0a47e520be4aa2b6c5d1b
冲突显示在冲突标记之间 <<<<<<<
和 >>>>>>>
。上半场(截至 =======
标记)是爱丽丝的当前版本,后半部分是鲍勃的版本。第二个冲突标记后面的40位十六进制数是两者最近的公共父级的SHA1散列。
现在,Alice的工作是通过协调它们的更改来解决冲突,例如通过编辑文件。她的结果是:
def fibonacci(i):
"""
Return the `i`-th Fibonacci number
"""
if i > 1:
return fibonacci(i-1) + fibonacci(i-2)
return [0, 1][i]
然后上传她的原始更改 and 她的合并承诺对GitHub Sage Repo::
[alice@laptop sage]$ git add fibonacci.py
[alice@laptop sage]$ git commit -m "merged Bob's changes with mine"
生成的提交图现在有一个循环::
[alice@laptop sage]$ git log --graph --oneline
* 6316447 merged Bob's changes with mine
|\
| * 41675df corrected recursion formula, must be + instead of *
* | 14ae1d3 return correct seed values
|/
* 14afe53 initial commit
[alice@laptop sage]$ git push origin
这一次没有合并冲突,因为Alice的分支已经合并了 develop
布兰奇。