GIT版本管理看这一篇就够了

timg.jpg

本文地址:https://www.jianshu.com/p/0e9d07ec76f9

一、简介

GIT基本上是目前最为先进的分布式版本控制系统,通过GIT能够非常方便的管理文件多个版本,能够实现版本的回滚,比对等功能,并且支持分布式也就是多人协同工作。

GIT也是目前使用作为广泛的版本控制软件,大名鼎鼎的Github网站能直接与GIT对接,使用GIT上传代码到Github之中。


二、GIT安装配置

通常来说,Linux系统使用各自版本对应的包管理工具可以非常方便的安装GIT。例如sudo apt-get install git,但安装之后会有一些设置需要配置。

1.1.中文乱码

安装GIT之后比较常见的一个问题,就是中文乱码,可以通过在命令行中设置解决:

git config --global core.quotepath false

1.2.配置身份信息

由于GIT支持多用户协作,所以在使用GIT之前,还需要配置身份信息。首先需要在GIT中配置你的用户名和邮箱地址:

git config --global user.name  "name"  // 名字
git config --global user.email "123@126.com"  // 邮箱

三、创建仓库

在使用GIT之前,得掌握一个仓库的概念,也就是repository。这个repository也就是一个目录,是GIT管理的单位,在一个repository中,所有文件的新建、修改、删除都会被GIT跟踪到,并加以管理,以便在以后进行还原等操作。

所以,使用GIT,首先要创建一个repository

创建一个仓库,主要可以有两种方式。

【init】

init的创建方式为从零开始创建一个仓库,首先需要有一个目录,使用cd进入到我们想要创建仓库的目录中,然后使用以下命令:

git init

即可将当前目录转化为一个repository。目录中会出现一个.git目录,里面保存着所有的版本信息。

【clone】

除了自己从零开始创建仓库外,还可以使用别人的远程仓库来创建,例如Github上有许多项目代码,都可以使用这种方式拷贝下来。

git clone git://git.kernel.org/pub/scm/.../linux.git

这样的话会在当前目录生成一个一模一样的仓库。


四、基础GIT命令

创建好仓库之后,就可以在仓库之中开始使用命令来控制此仓库文件的版本了。

在使用这些命令之前,还有几个GIT的基础概念需要掌握,分别是:工作区(working directory)暂存区(stage)分支版本库

  • 首先,工作区指的其实就是我们平常我们修改文件,查看文件的地方。
  • 暂存区则是类似于一个中转的区域,被叫做stage或者index。在工作区中修改了内容,那么首先需要先将修改提交到暂存区中,积累一定的修改数量,汇集成一个版本之后,再一起提交到具体的分支中。
  • GIT管理的项目中,有分支这个说法,可以理解为具体的开发方向,GIT仓库在初始化的时候会默认创建一个master分支,你的文件版本就实际保存在这些分支之中。
  • 暂存区分支合起来称为整个版本库。

【status】

在仓库中使用git status命令可以查看当前仓库的状态:

[root@southnorth lianjia]# git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   lianjia/settings.py
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   setup.py
no changes added to commit (use "git add" and/or "git commit -a")

其中主要列出了仓库当前所处的分支,被修改了的文件,以及没有被跟踪的文件。

参数

  1. -s - 以短格式显示仓库状态。

【add】

GIT仓库之中,虽然我们说所有的文件都可以被跟踪,但是这只限于文本文件的修改,GIT无法跟踪二进制文件的修改。

同时,在跟踪之前也需要先将文件添加到仓库的索引中,也就是说,使用add命令添加到索引中的文件,才会被GIT跟踪。在每次你新建或者修改了文件之后,需要你使用add命令将这个文件先添加到暂存区之中。

git add filename

运行了此命令之后,未跟踪文件将会从Untracked files:中转移到Changes not staged for commit:中。

有些时候,可能修改的文件比较多,一个个去用add命令去添加比较麻烦,所以也可以用*来匹配文件名,以下命令可以将所有未被跟踪的文件添加到暂存区中:

git add *

【commit】

在将新文件或者修改过后的文件添加到暂存区之后,就可以使用commit命令将其正式提交到仓库了。但是要注意的是,commit提交到仓库的文件状态,是最后一次执行add时文件的状态,而不是执行commit时文件的状态。

所以,在提交文件之前,最好都先使用git status检查一下,有没有需要添加的文件还没有用add添加到暂存区中。然后就可以运行命令了:

git commit

直接运行此命令后,会跳出一个编辑界面,一般默认是使用vim。如下所示:

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/master'.
#
# Changes to be committed:
#       modified:   "hello.md"

这里其实是需要你输入一些关于此次commit的一些信息,对此次代码提交做一定的标识,方便以后如果需要还原版本的时候清楚代码的改动。对此信息保存退出后,则commit提交成功。

参数

  1. -a - 虽然说可以使用add命令对commit提交的暂存区做很精细的改动,但是当提交的文件非常多的时候,则add起来会比较的麻烦。所以commit提供了-a参数,使用此参数,则会自动将已被追踪的修改过的文件添加到缓存区中,不用再手动add添加了。

  2. -m - commit提交的时候需要输入信息,有时候如果希望输入的信息比较少,则可以使用-m参数直接在命令行输入。如下所示:

    git commit -m 'message'
    

【rm】

如果需要移除仓库中已经被追踪的文件,那么最好使用GIT提供的rm命令来删除,会更加安全:

git rm filename

此删除命令会将磁盘上的文件一并删除,在commit后,此文件将不会再被追踪。

参数

  1. -f - 如果删除的文件已经被修改过,或者已经被添加到暂存区中,那么则需要用-f参数强制删除。这是一个保护措施,因为还未被提交的修改不会被保存下来,是无法恢复的。

  2. --cached - 如果希望某个仓库中的文件不再被GIT跟踪,但是依然被保存在磁盘里,这种时候可以使用--cached来删除。在错误的添加了文件到仓库中后,这个参数非常有用。

    git rm --cached filename
    

【reset】

使用GIT最大的一个好处是,GIT会将你提交的每个commit保存下来,以供你以后在出现问题后,能够非常方便的回滚版本。回滚版本的其中一个命令就是reset

在你将一些文件使用add命令添加到暂存区之后,使用git status命令查看状态时可以看到提示,如果想将添加到暂存区的文件取消暂存则可以使用以下命令:

git reset HEAD <file>...

在这里,HEAD代表的是最近一次的commit,此命令的意思则是将指定文件回滚到最近一次commit提交的状态。

如果没有指定文件的话,那么将会回滚整个仓库的状态,如下:

git reset HEAD

版本表示

回滚的时候可以指定回滚的版本,版本的表示方式有三种,默认情况下都是指向最近一次提交:

    • HEAD - 最近一个提交
    • HEAD^ - 上一次提交(倒数第二次提交)
    • HEAD^ ^ - 倒数第三次提交
    • HEAD^^^ - 倒数第四次的提交
    • HEAD~0 - 最近一个提交
    • HEAD~1 - 上一次提交(倒数第二次提交)
    • HEAD~2 - 倒数第三次提交
    • HEAD~3 - 倒数第四次的提交
  1. 每次提交的SHA1版本号。

参数

  1. --mixed - GIT的默认模式,使用此模式的时候,会清空暂存区,将回滚的内容全部恢复成未暂存的状态。也就是说不会修改任何本地工作区文件,只会回滚index和清空暂存区。
  2. --soft - 使用此模式,同样不会修改任何本地工作区文件,与--mixed的区别主要在于,其会将回滚的内容放入暂存区中。
  3. --hard - 此模式是一个比较危险的命令,使用此模式,将会把仓库彻底还原到commit的状态。如果你的暂存区和工作区中有修改了但未提交的内容,将会彻底丢失,所以谨慎使用此模式。

【diff】

git diff命令可以查看两次文件内容有什么不同。使用以下命令可以查看工作区和版本库中最新版本的区别。

git diff HEAD -- <filename>

在这里--表示的是工作区,HEAD表示的是最近一次commit提交的版本,还可以用--cached代表暂存区。

在没有指定的情况下,是默认查看工作区和暂存区的区别:

git diff <filename>

【log】

使用git log命令,将会用以下的格式输出提交的commit日志记录,如果记录较多的话,需要按q键退出查看。

$ git log
commit 69b8e6b3ebff7b84d6190a374475a20482d4c3ba (HEAD -> master, origin/master, origin/HEAD)
Author: wnanbei <wnanbei@gmail.com>
Date:   Thu Nov 15 17:16:53 2018 +0800

    add git branch part

commit 28056c5055ef9ed4156b74713c0205e8fde44713
Author: wnanbei <wnanbei@gmail.com>
Date:   Thu Nov 15 15:21:30 2018 +0800

    complete basic git command

commit 6f6aae904ad7551d49ab952e9e3afae70bc93c50
Author: wnanbei <wnanbei@gmail.com>
Date:   Thu Nov 8 17:19:46 2018 +0800

    add git

参数

  • --oneline - 每条commit日志只显示一行内容:

    $ git log --oneline
    69b8e6b (HEAD -> master, origin/master, origin/HEAD) add git branch part
    28056c5 complete basic git command
    6f6aae9 add git
    
  • --skip - 指定跳过前面几条日志:

    $ git log --skip=4 --oneline
    b9922fc add git
    edd4594 change the python file name
    a9cded2 add git article
    
  • -[length] - 指定输出的日志数量

    $ git log --oneline -2
    69b8e6b (HEAD -> master, origin/master, origin/HEAD) add git branch part
    28056c5 complete basic git command
    
  • --pretty= - 使用其他格式显示提交信息,可选项有:oneline、short、medium、full、fuller、email、raw,默认为medium。

  • --graph - 在左侧以图形的方式显示提交的commit变动,更清晰的展示分支的合并等信息。

  • --decorate - 展示更多的信息,例如HEAD、分支名、tag。

  • --author - 通过提交者的名字来搜索提交信息。

  • --grep - 从提交的关键字搜索提交信息。

  • -p - 通过路径搜索提交信息

    git log -p -- config/my.config
    

【tag】

GIT中还有一个非常方便的功能,就是打标签,可以给某个特定的commit进行标记。比较广泛的一个方式使用它来标记版本号。使用以下命令将会给当前分支最新的一个commit打上tag

git tag <tagname>

如果你需要指定给某个committag的话,则需要你在命令后面加上commit的id。

使用以下命令可以查看tag的信息:

git tag  # 查看本地所有tag
git show <tagname>  # 查看指定tag的详细信息
git ls-remote --tags <remotename> 查看远程所有tag

需要注意的是,我们创建的tag都是只存在于本地的,所以如果要把tag同步到远程仓库的话,需要额外单独的使用命令同步tag

git push <remotename> <tagName>  # 推送单个tag到远程仓库
git push <remotename> --tags  # 推送所有未推送的tag到远程仓库

参数

  • -a - 指定tag的名字。
  • -m - 给tag添加上备注的信息,与commit的信息类似。
  • -d - 这个参数代表删除tag。需要注意的是如果要删除远程的tag,则需要本地删除后,再push到远程仓库。

五、分支管理

GIT之中,有分支的概念。在这里举一个例子,你希望在你的工作项目上新增添一个功能,那么你就可以在当前项目的基础上新开一个分支,然后在这个专门的分支上开发的你新功能,而原来的工作项目不受任何影响。等到你的新功能开发完毕通过测试后,就可以将这个分支与之前的工作项目分支合并了。

这种开发方式,能够将工作从开发主线上分离开来,避免工作时影响到工作主线。

由于GIT的分支实现原理跟指针类似,所以创建切换合并分支都是非常迅速的。GIT也非常鼓励新建一个分支去完成任务,任务完成后和主分支合并,然后删除掉这个新分支,这样使用下来与直接在主分支工作是差不多的,但是安全性要高不少。

【branch】

首先,直接使用git branch命令是查看当前仓库的分支:

git branch

如果在git branch命令后面跟上一个名字,则可以在当前仓库新建一个分支:

git branch working

也可以使用当前分支的某历史版本创建分支,这样的话需要指定具体的commit的ID:

git branch working 169d2dc

需要注意的是,仓库一般默认会有一个master分支,这个分支其实并没有什么特殊,跟其他新建的分支没有什么区别,只是在git init时默认会创建这样一个分支,大部分人也懒得去修改。

参数

  • -d - 如果在创建之后需要删除一个分支,可以加上此参数。

    git branch -d working
    

【checkout】

在创建了分支之后,我们所处的依然是之前的分支,要切换到新的分支的话,依然是需要我们手动切换的。

git checkout working

参数

  • -b - 加上这个参数之后,则代表直接创建一个分支,并且切换到这个分支,也就是说可以省略掉git branch这个步骤。

【merge】

在创建了分支之后,大部分情况下最终都是要合并的,也就是将分支修改的内容和另一个分支的修改内容合并到一起。

使用git merge命令将可以把某一分支与当前分支合并到一起:

git merge working

如果两个分支之间没有冲突的话,那么分支的合并将会非常简单,GIT会自行决定如何合并两个分支。但是如果两个分支之间有文件冲突的话,也就是说两个分支内都对同一个文件进行了修改这种类似的操作,GIT将无法决定保留哪一个分支的内容。

因为在逻辑层面上,也需要由你自己来决定,在冲突的情况下,保留哪个分支的内容。在这种情况下,合并的时候会显示类似以下的内容:

CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.

在冲突的文件内,GIT会将两个分支的内容都放在了一起,由你自行修改:

<<<<<<< HEAD
i am master
=======
hello, i am working
>>>>>>> working

可以看到====分割上方的是当前分支的内容,下方是合并的working分支的内容。此时由你自行修改,处理完冲突之后,add添加好就可以提交了。


六、远程仓库

在前面讲的用法基本上都是本地的GIT用法,但是使用GIT很大的一个优势是可以多人协作,同时完成项目,那么这基本必然要涉及到远程仓库的使用。远程仓库可以自己在服务器上搭建,也可以使用一些其他人提供的仓库托管服务,例如Github这个全球最大的同性交友网站。

使用init命令生成的仓库中,是没有配置远程仓库的,需要自行配置。而如果是使用clone获取的仓库,则会将来源的远程仓库默认配置为一个名为origin的远程仓库,这个远程仓库没有什么特殊,只是默认起名而已。在一些比较复杂的多人合作项目中,会配置有多个远程仓库。

【remote】

使用git remote命令即可查看当前仓库有配置哪些远程仓库:

$ git remote
origin

如果你需要添加新的远程仓库,那么可以使用以下命令:

git remote add <shortname> <url> 

<shortname>是你给这个远程分支起的名字,这个名字只会在本地起作用。

以下还有一些显示与删除等命令:

git remote show [remote-name]  # 显示远程仓库详细的信息
git remote rename old_name new_name  # 重命名远程仓库
git remote rm remote_name  # 删除远程仓库

参数

  • -v - 会显示远程仓库的url。

【fetch】

在配置了远程仓库之后,就可以从远程仓库拉取内容了。这个命令会访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。

git fetch [remote-name]

如果需要只拉取某个分支的内容,需要在后面加上分支的名称。

git fetch origin master  # 拉取远程仓库origin中的master分支
git fetch origin master:temp  # 拉取远程仓库origin中的master分支,并命名为temp分支

需要注意的是,fetch这个命令只是将版本库中的内容拉取下来,并不会自动合并和修改你工作区中的内容,需要你自行手动合并。

之后需要合并拉取的内容到工作区的话,需要使用git merge命令。

git merge FETCH_HEAD

这里的FETCH_HEAD是一个版本链接,记录在本地的一个文件中,指向着目前已经从远程仓库取下来的分支的末端版本。

一般来说一个比较常见且安全的使用方式如下:

git fetch origin master:tmp  # 在本地新建一个temp分支,并将远程origin仓库的master分支代码下载到本地temp分支
git diff tmp                 # 来比较本地代码与刚刚从远程下载下来的代码的区别
git merge tmp                # 合并temp分支到本地的master分支
git branch -d temp           # 如果不想保留temp分支 可以用这步删除

【pull】

如果觉得使用fetch命令比较麻烦,且确定远程仓库的内容可以安全合并的话,那么可以使用pull命令。pull命令其实是一个混合命令,相当于把git fetchgit merge这两个命令合并到了一起,一个命令直接解决问题。

git pull origin

【push】

在多人协作完成项目时,本地工作完成后,需要推送到远程仓库中,这个时候需要使用git push命令来进行推送。这个命令的用法如下所示:

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

如果当前分支只有一个远程分支,那么主机名与分支名都可以省略:

git push

如果当前分支与远程分支存在追踪关系,则可以省略分支名,只留主机名,例如:

git push origin

如果只省略远程分支名,则表示将分支退送到与之存在追踪关系的分支,如果远程分支不存在,则创建新的远程分支:

git push origin master

如果只省略本地分支名,则代表删除指定远程分支:

git push origin :master

七、配置忽略文件

在使用GIT管理项目时,我们项目里常常会有一些文件是不需要纳入版本管理的,例如Mac系统的.DS_Store之类的默认文件,又比如Python的运行生成的__pycache__目录。

如果这种文件较多时,我们添加文件将变得比较的麻烦,所以GIT给我们提供了一个方式,可以忽略掉指定的文件。

首先是配置全局忽略,GIT管理的仓库都能起效。配置的方式有几种,我们这里主要使用.gitignore文件来进行配置。

首先我们需要创建一个.gitignore文件,这个文件放在哪里都可以,但推荐的位置是直接放到家目录中:

touch .gitignore

然后,我们需要将此文件配置到GIT中(如果有修改文件路径的话,这里需要相应的修改):

git config --global core.excludesfile ~/.gitignore

最后,我们再来编辑.gitignore文件,将需要忽略的文件写到这个文件中即可,文件内格式如下所示:

.DS_Store
__pycache__
*.pyc
.vscode

如果需要按照具体的项目来配置特定的忽略文件的话,那么可以配置一个.gitignore文件直接放到仓库的根目录即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • Git 基础 基本原理 客户端并不是只提取最新版本的文件快照,而是把代码仓库完整的镜像下来。这样一来,任何一处协同...
    __silhouette阅读 15,853评论 5 147
  • Git 命令行学习笔记 Git 基础 基本原理 客户端并不是只提取最新版本的文件快照,而是把代码仓库完整的镜像下来...
    sunnyghx阅读 3,902评论 0 11
  • Git常用语法 [TOC] Git简介 描述 ​ Git(读音为/gɪt/。)是一个开源的分布式版本控制系统,...
    君惜丶阅读 3,493评论 0 13
  • 天色渐渐亮起来的时候,江修还坐在床上摆弄那封信,信里放了一张卡片,只写了一句话:有些事既然开启,就要付诸全部的心...
    二丫的娜梅莉亚阅读 398评论 1 2
  • 天地间有神,人,鬼其中神是最大的。而灵魂摆渡人就是在人和鬼之间的摆渡者,他可以看到神,人,鬼,这三类人1987年,...
    aishdh阅读 814评论 0 2