跳转至

Git & GitHub

首先,在开始前,一定先区分开 Git 和 GitHub 的概念。

Git 是一个分布式版本控制系统,它可以帮助我们管理代码的版本,跟踪代码的变化,协作开发等等。Git 在每个开发者的本地都有一个完整的代码仓库,这样即使没有网络,也可以进行代码的管理。

而 GitHub 是一个基于 Git 的代码托管平台,它提供了 Git 服务,可以帮助我们把代码托管到远程仓库,方便我们协作开发。

1. 安装与注册

Git 的安装这里就略去了,可以参考 官方文档

注册 GitHub 账号也不详细展示了,可以直接访问 GitHub 进行注册。

2. 设置

2.1 Git身份设置

全局设置:

Bash
git config --global user.name {你的用户名}
git config --global user.email {你的邮箱}

项目设置:

在具体的项目(git 本地仓库)中,可以设置项目的用户名和邮箱,这样可以覆盖全局设置。

Bash
git config user.name {你的用户名}
git config user.email {你的邮箱}

2.2 生成 SSH 密钥

关于密钥

SSH 密钥是一种非对称密钥,它包括公钥和私钥,公钥可以公开,私钥不能泄露。在一个 SSH 会话中,客户端使用私钥对数据进行加密(签名),服务器使用公钥对数据进行解密(验证),从而保证数据的安全性。

常用的密钥类型有 RSA 和 ED25519,ED25519 是一种新的密钥类型,它比 RSA 更安全更高效,推荐使用。当前 GitHub 官方默认推荐使用 ED25519 密钥。

生成密钥时,会要求输入密码,这个密码是用来保护你的私钥的,如果你不想输入密码,可以直接回车,但是这样会降低你的私钥的安全性。

如果你是在别处生成的密钥并拷贝到这里,那么需要修改密钥的权限,来保证密钥的安全性。(如果你报错类似于 Permissions xxx for xxx are too open.,那么就是权限问题)可以通过以下命令修改到合适的权限:

Bash
chmod 600 ~/.ssh/id_rsa
Bash
cd ~/.ssh/
ssh-keygen -t rsa -C {你的备注,如邮箱} # -C: comment
ssh-keygen -t ed25519 -C {你的备注,如邮箱} # 现在推荐使用 ed25519

2.3 添加 SSH 配置

Text Only
Host github.com
    HostName github.com
    User {你的用户名}
    IdentityFile {私钥路径}
    ForwardAgent yes # 如果你使用 ssh-agent,可以添加这一行
    IdentityFile {私钥路径} # 如果你要指定私钥路径,可以添加这一行

2.4 ssh-agent设置

关于 ssh-agent

ssh-agent 是一个控制用于 ssh 私钥的生命周期的程序,它可以帮助你管理你的私钥,以便你不必每次使用 ssh 时都输入密码。

Linux

Bash
eval "$(ssh-agent -s)"
ssh-add {私钥路径}

Windows

PowerShell
Set-Service -Name ssh-agent -StartupType automatic
ssh-agent -s
ssh-add {私钥路径}

2.5 Git推送默认设置

Bash
git config --global push.default simple
此设置是 Git 命令 push 的默认模式为 simple,当我们执行 git push 没有指定分支时,自动使用当前分支,而不是报错。

3. 基本概念

3.1 git仓库构造

参考文章

3.1.1 基本状态模型

1664128075112.png

3.1.2 文件变化例子

1664128075113.png

3.1.3 工作区 (workspace)

就是我们当前工作空间,也就是我们当前能在本地文件夹下面看到的文件结构。初始化工作空间或者工作空间 clean 的时候,文件内容和 index 暂存区是一致的,随着修改,工作区文件在没有 add 到暂存区时候,工作区将和暂存区是不一致的。

3.1.4 暂存区 (index)

老版本概念也叫 Cache 区,就是文件暂时存放的地方,所有暂时存放在暂存区中的文件将随着一个 commit 一起提交到 local repository 此时 local repository 里面文件将完全被暂存区所取代。暂存区是 git 架构设计中非常重要和难理解的一部分。

3.1.5 本地仓库 (local repository)

git 是分布式版本控制系统,和其他版本控制系统不同的是他可以完全去中心化工作,你可以不用和中央服务器 (remote server) 进行通信,在本地即可进行全部离线操作,包括 log,history,commit,diff 等等。完成离线操作最核心是因为 git 有一个几乎和远程一样的本地仓库,所有本地离线操作都可以在本地完成,等需要的时候再和远程服务进行交互。

3.1.6 远程仓库 (remote repository)

中心化仓库,所有人共享,本地仓库会需要和远程仓库进行交互,也就能将其他所有人内容更新到本地仓库把自己内容上传分享给其他人。结构大体和本地仓库一样。

4. 基本使用

4.1 本地

  1. 查询文档

    Bash
    git help {command} # 查询命令文档
    

  2. 初始化

    Bash
    git init # 初始化
    # 创建本地git仓库
    

  3. 查看工作区、暂存区状态

    Bash
    git status # git状态
    # 上面命令将会向你输出:
    # - 存放在 Git 暂存区的文件及其状态
    # - 未纳入 Git 版本管理的文件(需要通过 git add 纳入)
    

  4. 添加到暂存区

    Bash
    git add {filename} # 将指定文件纳入到 Git 的版本管理中
    git add . # 同下,将项目所有文件纳入到 Git 的版本管理中
    git add -A 
    
    git rm --cached {filename} # 将暂存区的文件移除版本管理,此命令可以用来更新 .gitignore 文件的规则
    

  5. 提交到暂存区

    Bash
    git commit -m "{描述}" # 上面这行命令会将暂存区的文件都提交到 Git,-m 选项后面带的参数表示本次提交的简单描述。
    
    git commit -a -m "{描述}" # 执行add(对修改文件)再commit
    # 注意 untracked 的文件必须通过add纳入版本管理
    # 但已纳入git但被修改后可以通过上述命令一步到位commit
    

  6. 查看 git log / commit history

    Bash
    git log --oneline --graph --decorate --all # 命令行可视化查看git树
    git reflog # 显示可引用的历史版本记录
    

  7. 删除文件

    Bash
    git rm {filename} # git rm 只是在暂存区删除了文件,并没有提交更改
    git commit -m "{描述}" # 提交更改
    

  8. 版本回滚 本质:对HEAD指针进行操作

    Bash
    git reset {commit id} # 将Git仓库的 HEAD 回退到某版本,清空暂存区,但是不修改目录中的文件。
    git reset --hard {commit id} # 将 Git 仓库的 HEAD 回退到某版本
    git reset --hard HEAD^ # 使用^符号:只能往后退,(几个^就回退几步)
    git reset --hard HEAD~{n} # 使用~符号后退特定数量版本
    

    reset命令的三个参数对比:

    --soft:仅仅在本地库移动指针 --hard:在本地库移动HAED指针、重置暂存区、重置工作区 --mixed:在本地库移动HAED指针、重置暂存区(默认参数)

  9. 比较文件差异

    Bash
    git diff {filename} # 查看工作区和暂存区的差异
    git diff {commit} {filename} # 和本地库的某一版本进行比较
    git diff {commit1} {commit2} {filename} # 比较两个版本的文件差异
    

  10. 分支操作

    Bash
    git branch -v                      # 查看所有分支
    git branch {分支名称}                # 创建分支
    git branch -d {分支名称}             # 删除分支
    git branch -m {老分支名称} {新分支名称}  # 改名
    git checkout {分支名称}              # 切换分支
    git checkout -b {分支名称}           # 创建并切换分支
    

  11. 合并分支

    Bash
    git merge {分支名称} # 将{分支名称}分支 merge 进当前分支
    

  12. 解决冲突 删掉 git 的标记提醒,然后手动修改文件到满意的情况,然后 add,再 commit

4.2 远端

  1. 建立远程仓库 首先在 GitHub 上新建一个仓库,然后根据需求可以选择不同的方式进行初始化。

    关于远程仓库

    远程仓库地址可以是 https 或者 ssh 协议,ssh 协议需要按文章开头的介绍配置 ssh key,而 https 协议则需要输入用户名和密码(注意这里的密码是 GitHub 的 access token,而不是 GitHub 的登录密码,密码登录由于安全原因已被废弃,可以在 GitHub 的设置中生成 access token)。

    和文章开头一致,这篇文章主要介绍的是 ssh 协议的使用,所以这里不会详细介绍 https 协议的使用。

    此外,GitHub 也提供了一个通过 GitHub CLI 进行操作的方式,可以参考 GitHub CLI

  2. 设置远程仓库

    Bash
    git remote -v # 查看远程仓库
    git remote add {远程仓库名} {远程仓库地址} # 添加远程仓库,远程仓库名一般取 origin,所以下面均写为 origin
    git remote rm {远程仓库名} # 删除远程仓库
    

  3. 向远端仓库push

    Bash
    # 当未设置 upstream 时:
    git push -u origin {本地分支名称}[:{远程分支名称}] # 将本地<branch>分支推送至“在本地叫做origin”的远程仓库的对应同名分支,没有则新建,并记住这个分支,下次直接 git push 即可
    
    git push # 将本地 当前 分支推送至默认远程仓库(origin)中对应分支,需要在前面设置Simple 模式,并且每个分支需要先 push -u origin brach_name 一次,或手动设置 up-stream
    

  4. clone

    Bash
    git clone {远程仓库地址} # 克隆远程仓库
    

  5. pull

    Bash
    git pull # fetch + merge 的结合
    # 等价于以下两条命令
    git fetch origin main
    git merge
    

关于权限

直接把别人的远程仓库clone下来之后,修改完之后不能直接push,需要让远程仓库的拥有则把你加成 collaborators,否则只能将 remote 更改为自己的仓库地址,然后 push 到自己的仓库,再发起 pr。

4.3 .gitignore

常用ignore

4.4 .gitattributes

常用示例

Bash
* text=auto # 其中, * 代表所有文件, text=auto 是让 Git 自动判断文件是二进制文件还是文本文件并进行行尾转换。
*.ipynb linguist-vendored # 该行表示忽略所有 .ipynb 文件的语言统计

5. 协作

基本流程:参考

团队项目 - pull master到本地 - 新建branch x - 开发对应模块x - pr - 若期间master无修改,则将x push到远程repo,发起pr - 若期间master有修改,则checkout到master并先将master pull下来,再checkout test,把master merge到当前分支x,再将x push到远程repo,发起pr

社区项目

  • fork 到本地
  • pull master到本地
  • 新建branch x
  • 开发对应模块x
  • pr
    • 若期间master无修改,则将x push到远程repo,发起pr
    • 若期间master有修改,则checkout到master并先将master pull下来,再checkout test,把master merge到当前分支x,再将x push到远程repo
    • 发起pr

6. CI/CD

详见笔记

几条参考:

评论