Git 命令使用

Git 命令使用_第1张图片

简介

Git 作为分布式版本控制系统,基于去中心化的设计思想,在每个分布式节点上都保存有完整的版本,降低了对中心仓库的依赖,增加了版本安全性。

Git 的使用过程中,并不是必须设置中心仓库,各个节点之间完全可以互相推送和拉取更新内容。不过考虑到相互的通信问题和团队协作,所以一般会选择一个 24 小时运行的主机作为中心仓库,以此来获取和交换更新内容,例如 GitHub 则提供了这样的托管服务。

三种状态

Git 对文件的跟踪管理存在三个阶段,工作区、暂存区和分支:

  • 工作区就是实际操作的文件目录;
  • 暂存区是一个索引文件,记录已跟踪文件的目录树,保存文件的时间戳、大小等易比较的信息;
  • 分支与暂存区类似,也保存有文件的目录树,用于记录文件系统的快照。
Git 命令使用_第2张图片

暂存区和分支都依赖 .git/objects 目录,该目录称为对象库,记录了真实文件系统的快照。暂存区只是一个 index 文件,存放在 .git 目录中。当工作区文件发生修改时,将工作区中文件的时间戳和大小,与 index 中记录的文件时间戳和大小进行比较,可以快速的判断工作区文件是否发生了更改,然后再具体的进行工作区文件内容与 objects 中记录文件内容进行比较。

暂存区的作用更像是工作区和分支之间的一个缓冲区域,或者称之为 “预提交文件改动到分支” 的区域。暂存区的存在,允许我们在工作区和暂存区之间方便的进行文件修改的添加与撤回,以及对修改内容的分部分提交。例如当工作中需要修改两部分内容,目前只完成了一部分的修改时,可以将完成的这部分添加到暂存区,接着在工作区继续修改另一部分,需要提交到分支上时,则提交缓存区的内容,未修改完成的部分可以继续修改。

因为分支更重要的作用是维护文件系统的版本序列,与远程仓库的通信,所以如果没有暂存区的存在,那么我们的文件修改则只能频繁的与分支打交道,届时版本序列将变得复杂且不易于维护,且每个版本记录保存的是文件系统快照,若频繁的进行文件修改和提交,则仓库大小将快速膨胀。

Git 使用

Git 安装

下载安装 Git:| Mac OS X | Windows | Linux/Unix |

官网下载速度较慢,这里提供一个 Windows 版本的下载链接:Git for Windows


Git 配置

Git 安装之后,首先进行用户名和邮箱的配置,配置信息会记录到每次的提交记录中,并且当推送更新到 GitHub 上的项目时,会与 GitHub 账号进行匹配,在历史提交记录中会显示出用户头像,并且点亮提交次数。

通过 git config 命令进行用户名和邮箱配置时存在三种级别:

  • --system:当前机器上的配置,面向所有用户;
  • --global:当前用户的配置,面向当前用户的所有仓库;
  • --local:当前仓库的配置,只对当前仓库生效。

配置使用的优先级为:local > global > system,即范围小的配置会覆盖范围大的配置。
配置文件所在位置为:
system:etc/gitconfig
global:~/.gitconfig
local:.git/config

windows 系统中的位置为:
system:git 工具安装位置的 etc/gitconfig
global:当前用户主目录下的 .gitconfig
local:.git/config

配置方式为:

git config --global user.name "abc"
git config --global user.email "[email protected]"

查询配置方式为:

git config --global --list

一般只需要对当前用户进行配置即可,即使用 --global 级别,如果某个仓库有特殊安排,则可以在具体的仓库级别进行配置即可。不明确指定级别的话,默认设置的为 --local 级别。

对于版本号在 2.0.0 以上的 git,提供了一个简单的查询配置文件目录的命令:

git config --list --show-origin

本地仓库与远程仓库的通信方式有两种,一个是使用http方式,每次连接需要输入用户名和密码进行身份验证;另一个是使用ssh方式,在远程站点配置个人公钥信息,当本地仓库与远程连接通信时,通过自身的私钥完成身份认证。

ssh-keygen -t rsa -C '[email protected]'

使用该命令会根据提供的邮箱信息生成公私钥文件,过程中会提示输入文件存放地址和密码信息,全部回车忽略可以使用默认值。公私钥文件地址默认为~/.ssh/id_rsa~/.ssh/id_rsa.pub,密码默认为空,即不需要每次通信时输入密码验证。

将公钥文件id_rsa.pub的内容添加到远程站点的SSH key中即可。如果存在多个不同的远程站点,例如同时有githubgitlab,则可以生成两对公私钥文件,在~/.ssh下建立config文件,文件内配置不同站点使用不同私钥文件。

config文件示例:

Host github
    HostName github.com
    User root
    Port 22
    IdentityFile ~/.ssh/id_rsa
Host gitlab
    HostName gitlab.xxx.com
    User root
    Port 22
    IdentityFile ~/.ssh/id_rsa_gitlab

创建仓库

创建仓库有两种方式,选择本地工作目录初始化为仓库,或者从远程仓库克隆到本地。克隆仓库的方式在下面的内容中再进行讲述,这里首先使用初始化本地工作目录为仓库的方式。

进入选定目录,执行如下命令即可:

git init

命令执行之后,在当前目录中会生成 .git 文件夹,此时当前目录即为一个“崭新”的仓库。

之所以用“崭新”来描述仓库,是因为在执行仓库初始化命令后,无论当前目录下是否存在文件,.git 目录生成后都不存在 index 文件,objects 目录下的文件夹中也没有具体的文件生成。即此时暂存区和分支都为空,只有向仓库中添加文件后,才会生成暂存区 index 文件,objects 目录下才会生成文件。


记录文件/更新

首先要明确一点,工作目录中的文件只有两种状态,已跟踪和未跟踪,也就是已经纳入版本记录,和未纳入版本记录。使用上面的 git init 命令生成仓库时,工作目录中的所有文件都是未跟踪状态,从远程仓库克隆生成本地仓库时,工作目录中的所有文件都是已跟踪状态。

对于未跟踪文件,则无所谓文件是否发生了修改,因为不会跟踪记录该文件的状态。对于已跟踪文件,则会检测记录该文件是否发生了修改。

git add 

git add 命令面向两种对象,一个是将未跟踪文件纳入暂存区,进行跟踪记录;另外一个是将已跟踪文件的修改,添加到暂存区,记录文件的更新。当命令后跟着一个目录时,则递归添加目录及目录下所有文件。

git status

git status 命令用于查看文件的状态,未跟踪文件只有一种状态:文件未跟踪,或者称为未纳入暂存区,状态显示为 Untracked files。已跟踪文件有两种状态:一是纳入暂存区,等待提交到版本库,状态显示为 Changes to be committed;二是文件发生了修改,且修改部分尚未添加到暂存区,状态显示为 Changes not staged for commit


删除文件

git add 命令用于向暂存区添加文件,或记录文件的更新内容。若执行此命令后,发现该文件并不需要跟踪记录,或者已经添加到暂存区的文件更新内容需要取消,git 提供了相应的撤回操作命令。

git rm --cache 

git rm --cache 命令用于从暂存区移除对文件的跟踪。

git rm 

git rm 命令不仅从暂存区移除对文件的跟踪,并且从工作目录中也删除了该文件。

git rm --cache 命令和 git rm 命令都存在一个 -f 选项,用于强制删除。当已跟踪的文件发生了修改,并且修改未添加到暂存区时,则需要git rm --cache -f 命令才能从暂存区移除对文件的跟踪;当已跟踪的文件发生了修改,并且修改已经添加到暂存区时,则需要git rm -f 命令才能同时从暂存区和工作目录中删除文件。


删除更新

这里的更新有两种情况:

  1. 工作目录下已跟踪文件进行了更新,且更新内容尚未提交到暂存区;
  2. 工作目录下已跟踪文件进行了更新,且更新内容已经提交到暂存区。
git checkout -- 

git checkout -- 命令用于撤销第一种情况下的更新内容,可以理解为拿暂存区的文件内容替换掉工作区的文件内容。

git reset HEAD 

git reset HEAD 命令用于撤销第二种情况下的更新内容,可以理解为拿上个版本的系统快照替换掉暂存区的文件内容。

git checkout HEAD 

git checkout HEAD 命令能够同时撤销工作区和暂存区的更新内容,可以理解为拿上个版本的系统快照替换掉工作区和暂存区的文件内容。

因为容易引起工作内容丢失,所以使用 git checkout HEAD 命令时需要注意。


提交文件

工作中对每一个文件修改完成后,将修改内容依次添加到暂存区,当完成所有修改后,则提交暂存区文件到当前分支上。

git commit

git commit 命令用于提交暂存区文件到当前分支上,执行该命令后会打开文本编辑器提示输入提交信息。

可以直接执行 git commit -m 'commit message' 命令,将提交信息写入命令中。

git log

git log 命令用于查看提交历史,每个提交都会记录时间、用户信息、输入的 commit 信息及 commit 值 ,这里的 commit 值是一个 SHA1 校验和,在后续的版本回退中会使用到 。

git reflog

git reflog 命令用于查看 HEAD 变动历史,当执行提交、分支切换以及版本回退这类改变 HEAD 指向的操作时,都可以通过该命令查询出 HEAD 指向的提交值,即 SHA1 校验和。该命令更多时候用于版本回退时,若想撤销回退操作,恢复到回退之前的记录时,通过该命令可以查询到回退之前的校验和。


分支切换

分支的使用很广泛,修改 bug,或者开发新功能,都可以拉出一个新分支,等功能开发完成并测试通过后,再合并分支内容到主干分支上。

git 的分支使用中,不同的分支实际就是指向各个文件系统快照的指针,所以在诸多 VCSgit 提供了轻量级且高效的分支创建、切换操作。

Git 命令使用_第3张图片

HEAD 可以理解为一个指针,指向当前访问的分支。

git branch

git branch 命令用于查看当前的分支情况。

git branch 

git branch 命令用于创建新分支。

git branch -d 

git branch -d 命令用于删除指定分支。

git checkout 

git checkout 命令用于切换到指定分支。

git checkout -b 

git checkout -b 命令用于创建分支,并切换到新分支。相当于 git branch git checkout 两条命令合并到一起。


分支合并与冲突解决

当在功能分支上完成新需求的开发任务后,需要切换回主分支,并将修改内容回合到主分支上,删除该功能分支。

git merge 

git merge 命令用于合并指定分支的修改内容到当前分支上。

Git 命令使用_第4张图片
merge-1

以合并 dev 分支修改内容到 master 分支为例,若 master 分支的指向处于 dev 分支的直接上游时,如图 merge-1 所示,此时合并分支速度较快,因为只需要更改 master 分支的指向即可。

Git 命令使用_第5张图片
after_merge

此时的合并方式为 Fast-forward 方式,因为只需要更改分支的指向,所以速度较快,且不会产生新的提交记录。

Git 命令使用_第6张图片
merge-2

master 分支的指向不处于 dev 的直接上游,如图 merge-2 所示,则合并过程需要比较 C3 提交的修改内容与 C4 提交的修改内容。如果两个提交中不存在对 同一处文件内容 的修改,则此时可以顺利合并修改内容,并产生一次新的合并提交,如下图中的 C5;如果两个提交中存在对 同一处文件内容 的修改,则此时合并存在冲突,需要手动解决冲突并完成合并提交。

Git 命令使用_第7张图片
after_merge

merge-2 所示的合并方式为 recursive 方式,或者称之为三路合并方式。因为合并 C3C4 的提交,需要与公共上游 C2 相比较,以达到与 同一处文件内容 相比较的目的,所以该合并方式主要观察 C2C3C4三个文件系统快照,所以称为三路合并方式。因为复杂情况下公共上游并不想图中所示这么明显,可能需要进行多次迭代合并处理方可产生虚拟的公共上游,所以也称此方式为 recursive 方式。

git cherry-pick 

git cherry-pick 命令用于合并其他分支上的某次提交到当前分支上。

git cherry-pick ^..

git cherry-pick ^.. 命令用于将其他分支上从 起始到 结束的提交合并到当前分支上,包括起始和结束提交。

理想的 VCS 使用方式是,克隆、修改、提交代码,不存在任何的 bug 修改或者冲突解决问题,但这是不可能的,所以实际工作中总会遇到各样的情形。例如暂时不准备将某个特性分支的开发修改合入主干,但是又要引入特性分支的某次提交(bug 修改、配置管理或者安全处理),此时可以使用 cherry-pick 来将指定的提交合入主干。


关联远程仓库

在团队协作过程中,经常的场景就是团队的每位成员都 fork 一份项目代码到自己的个人库中,然后在自己的库里面做修改,修改完成再合入到团队的项目代码库中。所以我们的本地仓库一般关联两个远程仓库,一个是团队空间的项目代码,用于拉取最新更新内容;一个是个人库中的项目代码,用于推送个人修改内容。

git remote

git remote 命令用于展示当前仓库关联的远程仓库。

git remote add  

git remote add

命令用于为当前仓库添加关联的远程仓库。

git remote remove 

git remote remove 命令用于删除当前仓库关联的远程仓库。

git fetch 

git fetch 命令用于从远程仓库拉取最新分支信息。

git fetch 命令只会拉取分支信息,生成 / 远程分支,并不会为本地仓库生成分支。

git branch -u /

git branch -u / 命令用于将当前分支与远程分支进行关联,即建立关联关系。

git checkout -b  /

git checkout -b / 命令用于在本地仓库上新建分支,并与远程分支进行关联。

git push  

git push 命令用于推送本地仓库的分支到远程仓库上,相当于在远程仓库上建立新分支。命令 git push : 提供同样推送分支的作用,并且可以给远程分支命名。

使用该命令只会在远程仓库上建立新分支,并不会自动与当前仓库上的分支进行关联,git push -u 命令可以在推送分支的同时进行关联,所以一般在 github 网站上新建仓库时都会有类似的提示,表示用于从本地初始化仓库,然后推送到远程仓库上。

git push  :

git push : 命令用于删除远程仓库上的指定分支。

当使用 git clone 命令来构造本地仓库时,会自动建立本地分支 master,并与远程仓库分支 origin/master 进行关联。

当本地分支已经关联到远程分支之后,拉取更新和推送更新都变得较为简单。在分支上直接执行 git push 即可推送更新到关联的远程分支上,执行 git fetch 即可拉取关联分支更新,然后执行 git merge 即可合入更新到当前分支上。此外,git 还提供有命令可以直接拉取更新并合入到当前分支上,git pull 命令相当于合并了 git fetchgit merge 两个命令的功能。


版本回退

虽然有了暂存区可以检查待提交内容的正确性,但是仍不免有错误或不恰当的内容被提交,git 提供了在分支上回退版本记录的命令。

git reset  

git reset 命令用于回退版本到指定提交记录点。这里 commitIdSHA1 校验和,用于标识待回退到的提交记录点。回退的 level 有三种:

  • --soft:修改 HEAD 指向指定的提交记录点,并将指定记录到最新提交记录之间的修改回退至暂存区,工作区不受影响。

  • --mixed:修改 HEAD 指向指定的提交记录点,并将指定记录与最新提交记录之间的修改回退至工作区,暂存区会被清除。

  • --hard:修改 HEAD 指向指定的提交记录点,并将指定记录到最新提交记录之间的修改清除。

该命令不填写具体 level 时,默认级别为 --mixed。这里注意一下 --hard 的使用,该级别会清除工作区和暂存区的修改,即便撤销回退操作回到最新提交,工作区和暂存区的修改也不会恢复,所以谨慎使用。同理, --mixed 级别也会清除暂存区的修改,所以版本回退过程中,需要注意选择恰当的回退方式。

执行版本回退命令时,并不一定每次都要提供指定版本记录的校验和,也可以通过 HEAD 来指定回退到相邻的哪一个版本记录。HEAD^ 表示回退到上一个版本记录,HEAD^^ 表示回退到上两个版本记录,HEAD~n 表示回退到上 n 个版本记录。

git revert 

git revert 命令用于回退指定提交记录。

git revert 命令和 git reset 命令都可以用于回退版本,不同之处在于 reset 用于回退到指定提交记录,revert 用于撤销指定提交记录,并且产生一个新的提交记录。

除了对提交历史的变动不同之外,git revert git reset 命令使用的侧重场景也不同。reset 命令更多用于在本地分支进行回退,避免对团队其他人的提交产生影响;revert 命令则可以使用在公共分支上,当进行代码检视时,发现提交历史中的某一次提交存在 bug,则可以使用 revert 命令撤销那一次提交。

在本地仓库的分支上执行回退操作后,有些情况下可能要同步回退远程仓库。

git push -f

git push -f 命令用于同步回退当前分支关联的远程分支,因为当前分支的版本落后于远程分支,所以需要加 -f 选项,执行强制推送。


文件异同

通过 git status 只能查看出文件的状态以及是否发生了修改,并不能具体的展示出差异内容。

git diff 

git diff 命令为查看工作目录的文件与暂存区文件的差异,也就是查看从上次提交文件修改到暂存区后,到目前为止,工作目录的文件又做了什么修改。

git diff --cached 

git diff --cached 命令为查看暂存区的文件与当前分支的文件差异,也就是此次准备提交到分支上的有哪些修改内容。

git diff HEAD 

git diff HEAD 命令为查看工作目录的文件与当前分支的文件差异,也就是查看从上次提交文件修改到分支后,到目前为止,工作目录的文件又做了什么修改。

Git 命令使用_第8张图片

git diff 命令还有其他形式:

git diff  

git diff 命令为查看当前工作目录文件与其他分支文件差异。

git diff --cached  

git diff --cached 命令为查看当前暂存区文件与其他分支文件差异。

git diff   

git diff 命令为查看两个分支文件差异。

git diff   

git diff 命令为查看两个版本记录文件差异。

git diff命令可以将文件的差异保存为补丁patch文件,因为补丁文件相对于整个项目而言体量较小,所以在协作工作时,常用的方式为将自己的修改保存为补丁,发送补丁文件来提交自己的修改。

git diff  > 

该命令将当前分支与进行比较,将修改保存为补丁文件。

git diff方式生成的补丁文件,可以使用apply命令进行应用。diff的比较对象在前面已经提到过很多种,这里的仅作为示例,实际使用中可以自由发挥。

git apply --check 

该命令用于检查补丁文件是否可以顺利的使用。

git apply 

该命令用于使用diff方式生成的补丁文件。

使用diff,apply的方式应用修改,不会自动添加为commit记录,只会将修改应用到工作目录中,所以需要手动将修改提交到暂存区和版本记录中。

除了diff,apply方式之外,还可以使用format-patch来生成git专用的补丁文件,使用am命令应用补丁,使用format-patch命令比较差异时,每一次提交都会生成一个patch文件。

git format-patch -M 

该命令将当前分支与进行比较,将修改保存为补丁文件,-M表示比较的对象是分支。

git format-patch 

该命令将提交记录之后的所有提交都生成补丁文件。

git apply --stat 

该命令用于检查补丁文件的修改。

git apply --check 

该命令用于检查补丁文件能否顺利的应用。

git am 

该命令用于应用补丁文件。

am命令可以一次应用一个补丁文件,也可以将所有补丁文件放在一个目录下,一次应用所有补丁文件。使用该专用补丁方式,可以自动提交commit记录,即版本记录不需要手动添加。在执行am命令使用补丁文件之前,推荐先执行一次git am --abort命令,用于清空之前的应用补丁信息。


储藏修改

当工作过程中需要临时解决某个问题,即需要在主分支上拉取 bugfix 分支修复 bug 时,若当前特性开发分支 dev 上的工作还没有完成,无法立即提交。此时切换并拉取新分支会对工作目录的修改内容造成干扰,则此时需要把当前修改存储起来,保持工作目录的整洁,然后再建立bugfix 分支修复 bug

git stash

git stash 命令用于储藏当前工作目录的修改和暂存区内容到一个栈空间上,使得当前的工作目录和暂存区不存在任何修改,即保持干净状态。

git stash pop --index

git stash pop --index 命令用于恢复栈空间上的储藏到工作目录和暂存区,即恢复原状。命令的使用中若不加 --index 参数,则储藏会恢复到工作目录,暂存区会清空。

该命令不仅适用于分支切换时,对于之前提到的版本回退命令,若可能造成工作目录和暂存区内容丢失,则可以使用该命令来储藏信息。


分支误删恢复

git 的分支功能使用很频繁,并且处理效率很高,无论创建新分支或者删除分支,都能够得到快速反馈,原因在前面的内容中提到过,即分支和 HEAD 都是指向不同系统快照的指针。所以当工作中对分支执行了误删除时,可以根据系统快照的校验和很方便进行恢复。

git branch  

git branch 命令用于根据提交记录的校验和创建出新分支,因为分支只是一个指向系统快照的指针,所以可以使用 git log 查看提交记录,然后进行分支创建。

准确讲,这个命令是用于创建新分支出来,而不是恢复分支,不过创建的分支与原分支的内容相同,所以常使用该命令来完成分支恢复。

若不小心执行了 git push : 命令,删除了远程仓库的分支时,可以使用前面提到的 git push 命令,根据本地分支在远程仓库上创建一个新的分支。

当然,使用该方式恢复远程分支的前提是,本地分支保存了远程分支的修改记录,否则可能导致最新的提交丢失。

修改提交信息

在本地进行开发时,有些时候可能将暂存区修改commit之后才发现,有些文件还没有修改,或者有些文件修改没有添加到暂存区,如果想将本地的所有修改操作,作为一次commit记录进行提交,以方便后续查看工作历史,git提供了--amend参数完成重写上一次的commit信息。

git commit --amend -m 

将本地遗漏的修改添加到暂存区后,使用该命令可以将上一次的修改内容与本地修改内容合并,做为一次commit记录提交到版本历史中。

如果没有修改遗漏,只是单纯的想修改上一次的commit描述信息,也可以使用该命令。

你可能感兴趣的:(Git 命令使用)