「Tools」:Git and GitHub

这篇文章具体讲述了Git工具的基本本地库操作和与远程库交互的基本操作,包括使用GitHub进行团队外的协作开发。

Git

Git简介

Git历史:

Linux的代码管理:

1991 Linus本人手动合并代码

2002 使用BitKeeper商业软件,授予Linux社区免费使用版本控制

2005 Linus自己用C语言开发了一个分布式版本控制系统:Git

Linus: Talk is cheap, show me the code.

2008 Github上线


Git的优势:

  • 大部分操作在本地完成,不需要联网。

  • 完整性保证:每次提交进行哈希。

  • 尽可能添加数据而不是删除/修改数据,版本都在。

  • 分支操作快捷流畅,以快照的形式。

  • 与Linux命令全面兼容。

Git的结构

Git的结构

Git和代码托管中心

代码托管中心的任务:维护远程库

局域网环境:搭建GitLab作为代码托管中心

外网环境:可以用GitHub和码云作为代码托管中心

本地库和远程库的交互

团队内:

团队内交互

团队外:

团队外交互

fork:复制一份属于自己的远程库

开发新的内容后向库的拥有者 pull request拉取请求,原拥有者可以审核,审核通过后执行merge操作合并到自己的远程库的分支上。

Git命令行基本操作

本地库初始化

  • 初始化本地库

    git init

.git文件存放的是本地库相关的子目录和文件,不要删除和随意修改。

本地库设置签名

  • 形式:

    用户名:

    Email:

  • 作用:区分不同开发人员的身份

注:这里设置的签名与远程代码托管中心没有关系。

  • 命令:

    • 项目级别:设置签名仅在本地库起效(如果既有项目级别和用户级别的签名,按照项目级别为准)

      设置用户名命令:git config user.name ***

      设置用户邮箱: git config user.email *****@outlook.com

      该信息保存在.git/config文件中。

    • 用户级别:设置签名在当前操作系统的用户范围

      设置用户名命令:git config --global user.name ***

      设置用户邮箱命令:git config --global user.email ****

      该消息保存在系统文件~/.gitconfig文件

查看状态

  • 查看工作区、暂存区状态。

    git status

本地库版本信息查看

HEAD: 指针,表示当前版本的位置。

显示版本:

  • 完整的版本信息记录(包括完整版本哈希值、作者、提交时间)

    git log (空格向下翻页;b 向上翻页; q退出显示)

  • 一行只显示一个版本,简洁版。

    git log --pretty=oneline

  • 一行也只显示一个版本,终极简洁版,哈希值也只显示前面的一部分(当作该版本的局部索引)。

    git log --oneline

  • git reflog :跟踪本地库的历史更新,可以看到HEAD之后(“未来“)的版本。

    HEAD@{i}:i表示HEAD指针移动到该版本需要后退的步数。

工作区操作:添加/修改/提交/删除

对于这些命令,其实在使用git status 时,都会有相关提示。

  • 提交到暂存区(增加、修改、删除):git add <filename>

  • 撤销工作区的修改(discard changes in working directory)

    git checkout -- <file>

暂存区操作:添加/修改/提交/删除

对于这些命令,其实在使用git status 时,都会有相关提示。

  • 添加/修改:将工作区的文件添加到暂存区(/或更新暂存区的文件)。

    git add <filename>

  • 删除:将文件从暂存区删除

    git rm --cached <filename>

  • 提交:将暂存区的文件提交到本地库。(输入提交信息)

    git commit -m <message> [filename]

  • 修改后的提交:提交修改后的文件至本地库(已在暂存区有旧版本),同时更新暂存区和本地库。

    git commit -m <message> [filename]

版本前进/后退

本质是HEAD指针的移动。

  • 基于索引操作:版本可以后退和前进。(索引就是reflog形式下的局部哈希值)

    git reset --hard [局部索引值]

  • 使用^ : 版本只能往后退 。(基于reflog形式下的步数)

    git reset --hard HEAD^^ (后退两步)

  • 使用~n :版本往后退n步。

    git reset --hard HEAD~3

版本前进/后退reset命令的参数对比:

  • --soft

    • 仅仅在本地库移动HEAD指针。

      如下图,显得暂存区和工作区版本比本地库前进了一步。

      --soft命令
  • --mixed

    • 在本地库移动HEAD指针

    • 并重置暂存区,暂存区和本地库一致。

      如下图,显得工作区版本比本地库和暂存区版本前进了一步。

      --mixed命令
  • --hard

    • 在本地库移动HEAD指针
    • 重置暂存区
    • 重置工作区

删除文件后找回

前提:删除前,文件存在的状态提交到了本地库。

操作:

  • 删除的操作已经提交到本地库

    • 删除操作:

      1
      2
      3
      rm a.txt
      git add a.txt
      git commit -m "delete a.txt" a.txt
    • git reset --hard [历史版本指针位置]

  • 删除操作未提交到本地库

    • 删除操作:

      1
      2
      3
      4
      5
      //工作区删除
      rm a.txt
      //缓存区也删除
      rm a.txt
      git add a.txt
    • git reset --hard HEAD

比较差异

  • 工作区文件和暂存区文件比较

    git diff [filename]

  • 暂存区和本地库内容比较

    git diff --cached

  • 工作区文件和本地库文件比较,指针可以使用HEAD^

    git diff [指针] [filename]

  • 可以不加文件名,即比较全部文件。

  • 任意版本之间的内容比较:

    显示两次差异文件

    git diff 版本1hash/指针 版本2hash/指针 --stat

    具体显示差异文件

    git diff hash1/指针 hash2/指针 filename

分支管理

分支

分支:版本控制过程中,使用多条线同时推进多个任务。

Ucz94H.png

master: 主版本分支/部署到服务器运行的分支。

feature_ :开发其他功能的分支。

hot_fix: 热修复,bug修复分支。

分支的好处:

  • 并行:同时并行推进多个功能开发。
  • 独立:各个分支在开发过程中,如果有个分支开发失败,不会影响其他分支。

分支操作:创建/查看/切换/合并

  • 创建分支

    git branch <branch name>

  • 删除分支

    git branch -d <branch name>

  • 删除远程分支:

    • 查看远程分支:git branch -r
    • 删除本地的远程跟踪分支:git branch -r -d origin/branch-name
    • 删除真正的远程分支:git push origin : branch-name
  • 查看分支

    git branch -v

  • 切换分支

    git checkout [branch name]

  • 合并分支

    1. 切换到接受修改的分支(如master)

      git checkout [合并到的主分支]

    2. 执行merge合并操作

      git merge [有修改的分支]

解决合并分支后产生的冲突

冲突的表现,显示到有冲突的文件:

冲突文件内容

冲突解决:

  1. 删除文件中的特殊符号

  2. 协商再编辑文件

  3. 添加新文件

    git add [filename]

  4. 提交(注意:此时的提交不能带文件名)

    git commit -m "message"

rebase:整理分支

  • rebase 操作可以把本地未push的分叉提交历史 整理成直线。
  • rebase的目的:在查看历史提交的变化时更容易。

Git 基本原理

哈希算法

特点:

  • 得到的加密密文长度相同。
  • 算法确定,输入确定后,输出一定确定。
  • 输入数据发生一点点变化,输出的变化会很大。
  • Git底层采用SHA-1算法。

哈希算法保证了Git的数据完整性。

Git保存版本的机制

集中式版本控制工具(如SVN):保存的信息是每个基本文件和每个文件随时间逐步累积的差异。

Git是分布式的版本控制工具。

Git把数据看作是文件系统的快照(可以理解为当前内存版本的文件的索引),每次提交更新时Git对当前内存的全部文件制作一个快照并保存这个快照的索引。如果文件没有修改,Git不会重新存储该文件,只是保留一个连接指向之前存储的文件。

Git的提交对象:

UcvLm8.png

上图中,每个文件都有一个哈希值/索引,提交时新建一个树结点,其中包含指向每个文件的指针/索引,提交的对象包括该树结点的指针/哈希值。

Git版本对象链条:

Git版本对象链条

所以:

Git 分支的创建:等于新建一个指向版本的指针。

分支创建

Git分支的切换:改变HEAD指针所指的指针。

分支切换

Git分支版本的移动:分支指针的移动。

分支版本移动

GitHub

基本交互

创建/查看远程库地址别名

在GitHub创建远程库后

  • 在本地添加远程库地址别名

    git remote add [别名] [https/ssh 地址]

    git remote add orgin https://...

  • 查看当前所有远程库地址别名

    git remote -v

本地库内容推送到远程库

前提:本地库已添加远程库地址别名。

  • 在本地将本地库推送到远程分支

    git push [别名] [分支名]

    git push origin master

将远程库克隆到本地库

  • git clone https/ssh_address
  • 效果:完整把远程库下载到本地;添加origin作为远程库地址别名;初始化本地库(含有.git文件)

删除远程仓库文件

场景:项目开发初期.gitignore文件配置不正确,导致某些不需要的目录上传到git远程仓库上了。

  1. 预览预览将要删除的文件:git rm -r -n --cached 文件/文件夹名称
    -n 参数:执行命令时,是不会删除任何文件,而是展示此命令要删除的文件列表预览。
  2. 确定无误后删除文件:git rm -r --cached 文件/文件夹名称
  3. 提交到本地并推送到远程服务器:git commit -m "..."
  4. 修改本地.gitignore 文件并提交。

团队内协作

团队成员邀请

项目创建者在项目”Setting”-“Callaborators”里邀请成员。

拉取:同步本地库

  • 在本地pull操作同步本地库与远程库相同。

  • fetch:查看远程库分支,可以切换至远程库分支,查看远程库分支的文件具体内容,决定是否合并。

    git fetch [远程库地址别名] [远程分支名]

    • 切换至远程库分支

      git checkout orgin/master

  • merge:(切换至本地库master分支),合并远程库分支。

    git merge [远程库地址别名]/[远程分支名]

  • pull = fetch + merge

    git pull [远程库地址别名] [远程分支名]

注:如果是简单的修改,可以直接pull拉取,如果不确定远程库修改内容,可以先fetch后再合并分支。

本地拉取与远程库冲突

  • 冲突发生原因:不是基于GitHub远程库的最新版进行修改,就不能push,在修改之前必须pull。
  • pull拉取下来后如果进入冲突状态,就按照“分支冲突解决办法”

跨团队协作

  1. fork操作:复制一份远程库。

    团队外的人,在项目节目点fork,即可fork一份远程库,该远程库的来源是创建该库的开发者,而fork出的远程库的所有者是执行fork操作的人。

  2. clone操作:下载到本地库。

  3. push操作:本地修改,推送至远程库。

  4. pull request 请求:在远程库(代码托管中心GitHub)执行pull request请求,请求合并该修改到原远程库。

  5. (原远程库所有者)审核操作:确认是否合并。

SSH登陆

  1. 在当前用户的根目录,生产.ssh密钥目录

    ssh-keygen -t rsa -C email@address

  2. .ssh/id_rsa.pub 文件的内容复制到GitHub新建ssh密钥的窗口下。

  3. 创建ssh远程地址别名

    git remote add origin ssh_address

  • Git仓库和SSH-key关联

    ssh-add "id_rsa address

Git工作流

待补充[1]

Gitlab服务器搭建

待补充[2]

Reference

  1. Git工作流待补充
  2. Gitlab服务器搭建
Author

f1ed

Posted on

2020-07-18

Updated on

2022-08-18

Licensed under

CC BY-NC-SA 4.0


Comments