作为一名程序员,肯定会将人生大部分的时光交给了 Github,这个戏称为全球最大的同性交友网站。Why?因为程序员需要版本控制系统(VCS)来对代码进行管理。这样程序员就可以跟踪项目的变化细节,将选定的文件回溯到之前某个状态,以及各个成员在多人协同项目中的代码贡献等。本文是对版本控制软件 Git 的初步探索,完全可以支持日常多人协同开发。

简介

版本控制系统

版本控制系统Version Control System)是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。它不仅可以用于软件源代码的管理,而且对绝大多部分的文件(二进制文件不支持增量提交)进行版本控制。 它的发展经历了三个阶段,分别是本地化,集中化和分布式。相较于最简单粗暴的复制整个项目来保存不同版本的原始做法,这三个阶段在不断优化前者的劣势使版本控制这事越来越完善。

  • 本地化版本控制系统
    本地化版本控制系统采用某种简单的数据库来记录文件的历次更新差异。它解决了原始粗暴版本系统中备份文件太大,对比很不方便,不易管理等问题。其中典型代表叫 RCS, 它的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化,也叫差分编码);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
  • 集中化版本控制系统
    集中化版本控制系统(Centralized Version Control System)使用单一的集中管理的服务器来保存所有文件的修订版本,而协同工作的人都通过客户端连到这台服务器,获取最新的文件或者提交更新。它解决了多人协同的问题。其典型的代表是 SVN,CVS 以及 Perforce 等。

  • 分布式版本控制系统
    分布式版本控制系统(Distributed Version Control System)除了在服务端保留完整的历史版本信息,在任何一个客户端都保留了项目完整的历史记录。它解决的就是服务器单点故障或者中心数据库磁盘损坏的问题。其典型的代表是 Git,Mercurial 等。

Git简介

Git 是一个分布式版本控制软件,最初由林纳斯·托瓦兹创作,于2005年以 GPL 协议发布。最初的目的是为了更好的管理 Linux 内核开发而设计。优势的是它速度快,以及出色的合并追踪能力。至于它的诞生有个小故事。

Git 在管理项目时,在本地会有三个工作区域:Git 的工作区、暂存区和本地仓库。如下图所示:版本控制之Git初探-LMLPHP.

  • 工作区(Working Directory)
    工作区是指项目目录中除了 .git 文件夹之外的所有文件。在该工作区中的文件只有两种状态:已跟踪文件和未跟踪文件。而已跟踪文件又细分为已提交(committed),已修改(modified)和已暂存(staged)这三种状态。 文件状态如下图所示: 版本控制之Git初探-LMLPHP
  • 暂存区(Stage/Index Area)
    暂存区是工作区到本地仓库的一个过渡区。对应 .git/index 文件。
  • 本地仓库(Local Repository)
    存放已经提交的数据,push 的时候,就是把这个区的数据 push 到远程仓库了

GitHub简介

GitHu 是最大的 Git 版本库托管商,是成千上万的开发者和项目能够合作进行的中心。 大部分 Git 版本库都托管在 GitHub,很多开源项目使用 GitHub 实现 Git 托管、问题追踪、代码审查以及其它事情。说白一点就是将 GitHub 当做远程仓库,并实现本地仓库和远程仓库的准实时同步。这样即使本地仓库发生异常,也可以通过远程仓库来恢复。

实际中用 Git 对项目进行版本控制的操作图: 版本控制之Git初探-LMLPHP

图中 workspace 代表当前工作区,index代表暂存区,也叫索引,Repository 代表本地仓库,而 Remote 代表远程服务器上的仓库,这里一般指 GitHub/Gitlab/Gitee 等网站的服务器.

Git文件结构

  • 文件夹:

    • branches
    • hooks 客户端或服务端钩子脚本
    • info 保存了一份不希望在 .gitignore 文件中管理的忽略模式 (ignored patterns) 的全局
    • logs 存储日志的文件夹
    • objects 存放 Git 对象
    • refs 存储指向各个分支的指针(SHA-1标识)文件
  • 文件

    • HEAD 指向当前分支
    • config 包含了项目特有的配置选项
    • description 仅供GitWeb 程序使用
    • index 保存了暂存区信息

Git 操作详解

  • git clone 从远程主机克隆一个版本库

    # 用法 从版本库的网址上拷贝文件到本地文件夹
    git clone <版本库的网址> <本地目录名>
    # 用例 支持多种文件协议
    git clone http[s]://example.com/path/to/repo.git/  # http协议
    git clone ssh://example.com/path/to/repo.git/      # ssh协议
    git clone git://example.com/path/to/repo.git/      # git协议
    git clone /opt/git/project.git                     # 本地文件
    git clone file:///opt/git/project.git              # 本地文件
    git clone ftp[s]://example.com/path/to/repo.git/   # ftp协议
    git clone rsync://example.com/path/to/repo.git/    # rsync协议
    
  • git remote 管理远程主机名

    # 用法
    git remote add <主机名> <网址>    # 添加远程主机名
    git remote rm <主机名>           # 删除远程主机名
    git remote rename <原主机名> <新主机名>   # 更改原主机名
    git remote show <主机名>         # 显示主机名的详细信息
    
  • git fetch 将远程主机的版本库更新取回本地(clone是从无到有,fetch是从有到有

    git fetch <主机名> <分支名>
    
  • git branch/checkout/merge/rebase 管理分支(Git 最大的特色

    # 用法 查看分支情况
    git branch -r    # 查看远程分支
    git branch -a    # 查看所有分支,远程分支以remotes/开头
    # 用法 创建新分支
    git checkout -b newBranch origin/master   # 在origin/master的基础上创建新分支
    # 用法 合并分支
    git merge origin/master      # 将origin/master分支合并到本地分支
    git rebase origin/master
    
  • git pull 取回远程主机某个分支的更新,再与本地的指定分支合并

    git pull <远程主机名> <远程分支名>:<本地分支名>
    # 等价于
    git fetch <远程主机名> <远程分支名>
    git merge <远程主机名>/<远程分支名>
    
  • git push 将本地分支的更新,推送到远程主机

    git push <远程主机名> <本地分支名>:<远程分支名>
    

Linux 下实战(以 Ubuntu 为例)

安装

  • 安装 Git

    sudo apt-get install git
    
  • 配置SSH Keys

    # 以 yuguoliusheng@gmail.com 创建 ssh key,并将私钥保存在 github 文件中,公钥保存在 github.pub 文件中
    ssh-keygen -C "yuguoliusheng@gmail.com" -f ~/.ssh/github
    
  • 配置 GitHub
    登录自己的 GitHub,依次点击 Settings => SSH keys => Add SSH key,将 github.pub 中的公钥添加进去.

  • 验证成功

    # 执行命令
    ssh -T git@github.com
    # 提示
    Hi yuguoliusheng! You've successfully authenticated, but GitHub does not provide shell access.
    
  • 配置git的个人信息

    # 设置用户名
    git config --global user.name "yuguoliusheng"
    # 设置email邮箱
    git config --global user.email "yuguoliusheng@gmail.com"
    

使用

  • 为已有的项目 project 创建代码仓库

    # 在项目 project 的根目录执行以下命令
    
    # 创建README.md文件
    echo "# Git 初探" >> README.md
    # 创建一个空的 git 版本库(创建 .git 文件夹)
    git init
    # 添加所有文件到暂存区域
    git add *
    # 将暂存区域文件提交到本地仓库,并标注信息“initial project”
    git commit -m "initial project"
    # 添加远程主机名 origin,它代表网址 https://github.com/yuguoliusheng/introduce.git
    git remote add origin https://github.com/yuguoliusheng/introduce.git
    # 将本地的 master/main 分支推送到 origin 主机上的 master/main 分支,并设定 origin 为默认主机
    git push -u origin master/main
    
  • 从远程服务器上克隆一个仓库到本地

    # 从 https://github.com/yuguoliusheng 上克隆 introduce.git 到本地 introduce 文件夹
    git clone https://github.com/yuguoliusheng/introduce.git introduce
    
  • 忽略某些文件或文件夹 有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件,像是日志或者编译过程中创建的等等。可以创建 .gitignore 文件来屏蔽这些

    # 此为注释 – 将被 Git 忽略
    *.a        # 忽略所有 .a 结尾的文件
    !lib.a     # 但 lib.a 除外
    /TODO      # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
    build/     # 忽略 build/ 目录下的所有文件
    doc/*.txt  # 会忽略 doc/notes.txt, 但不包括 doc/server/arch.txt
    
  • 查看提交的更新

    # 查看提交的日志,并显示最近两次提交更新区别
    git log -p -2
    
  • 存储当前工作空间 储藏 stashing 可以获取你工作目录的中间状态——也就是你修改过的被追踪的文件和暂存的变更——并将它保存到一个未完结变更的堆栈中,随时可以重新应用。

    # 存储当前工作空间,以方便进行切换
    git stash
    # 此时工作空间所有文件的状态就干净了,可以切换到其他工作空间
    
    # 显示之前存储的工作空间
    git stash list
    
    # 重新启用存储的工作空间
    git stash apply stash@2
    
    # 移除存储的工作空间
    git stash drop stash@2
    
    # 从存储中创建分支
    git stash branch testchanges
    

参考文献

  1. Git Pro第二版
  2. 百度百科VCS
  3. 维基百科Git
  4. 本地版本控制系统RCS
  5. 维基百科之差分编码

`如果该文章对您产生了帮助,或者您对技术文章感兴趣,可以关注微信公众号: 技术茶话会, 能够第一时间收到相关的技术文章,谢谢!

版本控制之Git初探-LMLPHP`


本篇文章由一文多发平台ArtiPub自动发布
03-09 21:13