Git

版本控制工具

版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。版本控制能方便查看更改历史,备份以及恢复以前的版本,保证多人协作不出问题。

Git对待数据的方式,更像是把数据看作是对小型文件系统的一组快照。每次提交更新或者在Git中保存项目状态时,它主要对当时的全部文件制作一个快照保存这个快照的索引。为了高效,如果文件没有修改,Git不再重新存储该文件,而只是保留一个链接指向之前存储的文件,Git对待数据更像是一个快照流


安装Git和TortoiseGit

TortoiseGit

TortoiseGit提供了Git的图形化操作界面,Git工作区的目录和文件的图标符加了标识版本控制状态的图像,可以非常直观地看到哪些文件被更改了需要提交。通过对右键菜单的扩展,可以非常方便操作Git版本库。

通过设置,选择Git提供的ssh客户端,这样**在下载ssh协议的代码仓库时,命令行与图形界面都可以使用同一套公钥和密钥。


Git基本配置

3种配置等级

  1. 系统配置:git config --system

    所有用户都有效,存放在git的安装目录下:%Git%/etc/gitconfig

  2. 用户配置:git config --global

    只对当前用户有效,存放在用户目录下:~/.gitconfig

  3. 仓库配置:git config --local

​ 只对当前项目有效,存放在项目目录下:.git/config


配置个人身份

1
2
git config --global user.name "Hunter"
git config --global user.email hspecial@163.com

这个配置信息会在Git仓库提交的修改信息中体现和Git服务器认证使用的密码或者公钥密码无关


文本换行符配置

这一节的内容仍然是给我造成困惑的部分,感觉从参考资料来看,跨平台的项目开发应该要自动转换换行符。但是在我目前有限的开发经验来看,似乎并没有对项目造成影响,怀疑可能是IDE完成了相应的工作。

默认的配置状态为:core.autocrlf=true,暂且不去作修改,待日后有了深刻的理解再来完善本节内容。


编码配置

  • 中文编码支持

    • git config --global gui.encoding utf-8

      图形化界面采用的编码

    • git config --global i18n.commitencoding utf-8

      git commit log存储时,采用的编码

    • git config --global i18n.logoutputencoding utf-8

      查看git log时,显示所采用的编码

  • 显示路径中的中文

    git config --global core.quotepath false


与服务器的认证配置

http/https协议认证

添加HTTPS证书信任:git config http.sslverify false


SSH协议认证

使用公钥认证,无需输入密码,加密传输,操作便利又保证安全性。


配置过程
  1. 生成公钥

    在bash命令行中输入如下命令:

    1
    ssh-keygen -t rsa -C "hspecial@163.com"

    一路回车,就能在用户目录下~/.ssh中,生成公钥id_rsa.pub

  2. 添加公钥id_rsa.pub中的内容到代码平台


新增公钥

出于某些情况,你可能要在另外的平台或者另外的项目,使用不同的邮箱来生成公钥,以便和代码平台的账号相匹配

  1. 生成公钥

    提示Enter file in which to save the key(输入要保存密钥的文件,即id_rsa文件)”时,输入密钥文件的保存位置。为了和用户配置等级的密钥区分,我选择在默认公钥的目录下创建对应的平台或项目名的文件夹。输入保存密钥的文件绝对路径即可。

  2. 添加公钥id_rsa.pub中的内容到代码平台


Git基本命令

Git版本控制下的工程区域

  1. 暂存区 stage

    一般存放在工程根目录.git/index文件中,因此也可以把暂存区叫做索引。

  2. 工作区 working directory

    日常工作的代码文件或者文档所在的文件夹。

  3. 版本库 Repository

    .git文件夹就是Git的版本库,也可以叫本地仓库


Git版本控制下的三种文件状态

  1. 已修改 modified

    修改了某个文件,但还没有提交保存

  2. 已暂存 staged

    把已修改的文件放在下次提交时要保存的清单中

  3. 已提交 committed

    文件已经被安全地保存在本地数据库中


常用命令

工程准备

  • git init:本地目录下新建git项目仓库

  • git clone [URL]复制远端工程到本地

    如果所在的项目Git服务器已支持git-lfs对二进制文件进行了区别管理,那么复制工程的时候**务必使用git lfs clone [URL]**,否则克隆操作无法下载到工程中的二进制文件,工程内容不完整。


查看修改

  • git diff:查看工作区的修改内容(当前索引与上次提交/任意两个节点(分支)之间的差异)

    • git diff --cached:当前索引与上次提交之间的差异

    添加--name-status参数,可以只看文件列表

  • git status:查看工作区和暂存区的文件状态

    该命令能看到修改的git文件是否已被暂存,新增的文件是否纳入了git版本库的管理。

    • Untracked files:新建但未被跟踪的文件
    • Changes not staged for commit:修改但未被暂存的文件
    • Changes to be committed:已修改并已暂存的文件

文件修改后提交推送

  • git add新增文件到暂存区

    把文件添加到暂存区,是提交修改文件之前的必要操作。如果文件已经被git追踪,即曾经提交过,在Git的早期版本中,需要git add再提交;在较新的版本中,无需git add即可提交

  • git rm删除文件到暂存区

    执行git rm后,通过git status查看时,会有deleted: xxx的提醒。之后进行提交,对应的文件就不再受git工程的管理直接从硬盘中删除文件,然后对该文件执行git commit,git会自动将删除的文件从索引中移除,效果相同

  • git mv移动文件到暂存区

    相当于mv操作的基础上,用git将操作传入了暂存区。

  • git commit提交更改的文件

    将暂存区中的文件改动提交到本地的版本库,一般需要附带提交描述信息,所以常见的用法是:

    git commit file_name -m "commit message"

    如果要一次性提交所有在暂存区改动的文件到版本库,可以执行git commit -am "commit message"

  • git push:将本地版本库的分支推送到远端对应的分支

    常见的推送命令格式:git push origin branch_name:new_branch_name

    new_branch_name是推送成功后,在远端服务器上的分支名:new_branch_name可以不写,远端分支名就和本地分支名相同。


查看日志

  • git log:查看当前分支上的提交日志

    git log默认按提交时间的由近到远列出所有的历史提交日志,每个日志基本包含:

    1. 提交节点
    2. 作者信息
    3. 提交时间
    4. 提交说明
    • --name-status

      能列出涉及改动的具体文件


分支管理

  • git branch:列出所有本地分支

    如果想查看远端服务器上的分支,-r即可,返回的分支名带origin前缀,即表示在远端。如果想查看远端和本地的所有分支,-a即可。

  • 新建分支

    默认基于当前节点创建分支

    • git checkout -b new_branch_name 新建后会自动切换到新分支
    • git branch new_branch_name 新建后不会切换到新分支
  • 删除分支

    • git branch -d branch_name

    • git branch -D branch_name 大写的D表示强制删除

      当目标分支上包含未合并的改动,则需要通过强制删除来操作。

    • git branch -d -r branch_name 删除服务器上的远程分支

      删除后还需要推送到服务器git push origin : branch_name

  • 切换分支

    • git checkout branch_name

    • git checkout -f branch_name

      如果当前分支工作区存在修改未提交的文件,与目的分支上的内容冲突,会导致切换失败,则需要使用git checkout -f进行强制切换

    checkout的对象可以是分支,也可以是某个提交节点或者节点下的某个文件

  • 从远端更新分支

    • git pull origin remote_branch:local_branch

      从远端服务器中获取某个分支的更新,再**与本地指定的分支进行自动合并(merge)**,如果远程指定的分支与本地指定的分支相同,则可以直接执行git pull origin remote_branch

    • git fetch origin remote_branch:local_branch

      git pull不同,git fetch在获取到更新后,不会自动合并,而是留给用户一个操作空间,确认git fetch内容符合预期后,再决定是否手动合并节点


分支合并

合并目标分支内容到当前分支,以下两种方式都可以达到目的

  • git merge branch_name

    git会将指定的分支与当前分支进行比较,找出二者最近的一个共同节点base,之后将指定分支在base之后分离的节点合并到当前分支上实际上是分支之间,差异提交的节点的合并

  • git rebase branch_name

但是二者的实现机制和对合并后节点造成的影响有很大差异,有者各自的风险


撤销操作

  • git reset commit_id

    可将工作区内容回退到历史提交节点

  • git checkout .

    回退本地所有未提交的修改。这是一条有风险的命令,不给用户任何确认机会。它会取消本地工作区的修改,用暂存区的所有文件直接覆盖本地文件,达到回退内容的目的

    如果仅仅想回退某个文件的未提交改动,可以使用git checkout -filename;如果想将工作区回退到某个提交版本,可以使用git checkout commit_id