美文网首页
git教程笔记

git教程笔记

作者: dy2903 | 来源:发表于2018-02-04 11:47 被阅读21次

    Git是什么

    Git能解决什么问题

    Git能解决什么问题?答曰:版本控制。

    经常写文档的同学应该比较清楚,对某个文档修改了一点以后,又不想直接覆盖,这样的话,后面发现写错了,就恢复不回来。所以就复制出很多文件名不一样,但是内容差不多的文件。

    这样也不是不可以,但是问题在于,Copy了很多份,太消耗空间。同时查找恢复也并不方便。

    所以我们希望有这样一种软件,它可以

    • 自动记录文件的改动
    • 可以团队协作编辑

    比如这样

    版本 文件名 用户 说明 日期
    1 service.doc 张三 删除了软件服务条款5 7/12 10:38
    2 service.doc 张三 增加了License人数限制 7/12 18:09
    3 service.doc 李四 财务部门调整了合同金额 7/13 9:51
    4 service.doc 张三 延长了免费升级周期 7/14 15:17

    其实仅仅是对Word文档进行版本控制,我觉得有道云协作就可以了,但是它需要使用外网,而且不是利用Windows自带的目录,感觉还是不太方便。

    分布式版本控制平台

    其实版本控制器还有很多,比如CVS和SVN,但是它们都是集中式的控制系统。

    所谓集中式,自然有个Master级别的角色,它可以保存所有的版本库。大家需要先从版本库里面获得最新的版本,修改以后再上传。这样Master自然就有了所有分支最新的版本了。

    缺点是必须联网,是不是很类似与上面说到的有道云笔记啊!

    那分布式版本控制系统有啥区别呢?分布式系统没有Master这个角色,所有的终端一视同仁,每个人都有一个完整的版本库。那怎么协作呢?只需要互相通信,互相推送就可以了。

    分布式系统的优点在于安全,一个人的电脑坏了,还有其他人的电脑作为备份嘛。

    当然在实际应用的时候,一般不会有两个人互相推送,还是会引入一个中央服务器,但是它就类似于一个交换机,只是用来交互数据,没有它大家也可以在本地干活。

    而且Git还有强大的分支管理功能,还是免费的。现在最快、最简单也最流行的就是Git了。

    安装Git

    • Linux上安装
    sudo apt-get install git
    

    配置

    首先要进行全局设置:

    $ git config --global user.name "Your Name"
    $ git config --global user.email "email@example.com"
    

    提交版本

    创建版本库

    什么是版本库?就是仓库,respository,可以理解为一个目录,里面的所有文件可以被Git管理起来,里面的文件修改、删除都跟跟踪到。

    下面来创建版本库,

    在需要创建版本库的地方里面打开cmder,输入

    git init
    

    当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的

    某些文件不提交

    有些时候需要把某些文件放到目录中,但是又不能提交它。可以在Git工作区建立一个.gitignore文件,里面填充要忽略的文件名

    我们可以通过.gitignore网站查看各种配置文件,组合一下即可用。

    一般需要忽略那些文件呢?

    • 操作系统自动生成的文件或者编译生成的文件。
    • 忽略敏感信息,比如密码
      比如Python里面,
    # Windows:
    Thumbs.db
    ehthumbs.db
    Desktop.ini
    
    # Python:
    *.py[cod]
    *.so
    *.egg
    *.egg-info
    dist
    build
    
    # My configurations:
    db.ini
    deploy_key_rsa
    

    有的时候,想添加一个文件到Git,发现添加不了,多半是被忽略了。可以使用

    git add -f <文件>
    

    也可以看是哪条规则限制了这个文件的上传

    git check-ignore -v <文件>
    

    将文件提交到版本库里面

    所有的版本控制系统都只能跟踪文本文件的改动,比如TXT文件、代码等。

    对于图片、视频、Word等都是二进制文件,虽然仍然可以由版本控制系统管理,但是没有办法对比文件系统的变化。也就是说通过Cmder无法对比两个版本之间的差别。

    所以使用Git主要还是针对于代码文件、TXT文件等进行版本控制,需要注意的是

    使用windows进行编码的时候,建议使用Notepad++将默认编码设置为UTF-8 without BOM

    添加文件到Git仓库,分两步:

    • 第一步,使用命令git add .,注意,可反复多次使用,添加多个文件;
      要随时掌握工作区的状态,使用git status命令。
      如果git status告诉你有文件被修改过,用git diff readme.txt可以查看修改内容。
      git diff HEAD -- readme.txt可以看查看工作区和版本库里面最新版本的区别

    • 第二步,使用命令git commit -m "备注"进行正式提交。
      实际上每次执行git commit -m就保存了一次快照,类似于打游戏的时候存一次档。如果我们想回退的话,可以通过快照来进行恢复rollback
      可以使用git log --pretty=oneline命令显示从最近到最远的提交日志,以时间轴的形式显示日志提交。

    版本回退

    上面一章我们讲了,可以使用git commit进行提交,然后使用git log --pretty=oneline查看有提交的版本。

    $ git log --pretty=oneline
    3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
    ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
    cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
    

    其中类似3628164...882e1e0的是commit id(版本号),为了保证多人提交的环境下,commit id不同,所以Git使用了SHA1计算出来的一个非常大的数字,用十六进制表示,这样就可以避免冲突了。

    Git就会把每个版本自动串成一条时间线

    image.png

    如何进行版本回退

    首先,Git必须知道当前版本是哪个版本,

    • HEAD表示当前版本,
    • 上一个版本就是HEAD^
    • 上上一个版本就是HEAD^^
    • 当然往上100个版本写成HEAD~100

    然后使用git reset开始回退

    git reset --hard HEAD^
    

    如果发现回退错了,所以想回到最开始的版本。

    • 如果命令行窗口还没有被关掉,可以顺着往上找直到找到那个版本的ID是3628164...,于是就可以指定回到未来的某个版本:
    $ git reset --hard 3628164
    
    • 如果命令行窗口关闭了,可以使用git reflog来查看执行commit命令时候的commit id。然后使用git reset

    总结一下:
    现在总结一下:

    • HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id

    • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。

    • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

    几个概念

    首先解释几个名词:

    • 工作区:指的是建立了git的目录,也就是平时我们进行代码编辑的地方
    • 版本库:工作区有一个隐藏目录.git,是Git的版本库。
      版本库里面有暂存区(Stage)、分支(Master)以及指向分支的指针HEAD
      其中Git区别于其他的版本控制系统的一个不同之处就是有了暂存区

    git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。

    image.png

    理解了这个,我们来可如下的过程

    第一次修改 -> git add -> 第二次修改 -> git commit

    可以发现第二次修改以后并没有git add,也就是第二次修改的内容没有放到暂存区,所以git commit不会把第第二次的修改提交了。

    这就是Git比其他版本控制系统优秀的地方,因为Git跟踪管理的是修改,而不是文件

    没有提交到分支之前的撤销

    之前我们说到了如果已经git commit到分支以后,要进行版本回退应该怎么做。

    但是如果我们只是添加到了暂存区,甚至还没提交到暂存区,此时应该如何撤销呢?

    • 只是修改,没有add到暂存区:
    git checkout -- file
    

    使用这个命令还可以把误删的文件恢复回来

    • 已经add到暂存区,但是没有commit
      • 首先使用git reset HEAD file回退到工作区。
      • 然后使用git checkout -- file把工作区的修改撤销了。

    总之,记住一点:git checkout -- 文件命令,撤销的是工作中文件的修改,而git reset HEAD -- 文件命令,撤销的是暂存区中文件的修改。

    撤销本地所有修改

    git checkout . #本地所有修改的。没有的提交的,都返回到原来的状态
    git stash  #把所有没有提交的修改暂存到stash里面。可用git stash pop回复。
    git reset --hard HEAD #返回到某个节点,不保留修改。
    

    分支

    分支有什么用?每个人可以创建自己的分支,想提交就提交,直到完成所有的功能以后,一次性合并到原来的分支上,这样可以不影响别人工作。

    Git好就好在切换分支只需要不到1s,比SVN等快很多。

    创建分支

    Git默认有一条主分支,即master分支,而HEAD指针实际上指向当前分支的,此时就是master

    image.png

    当创建新的分支后,Git新建了一个指针devHEAD指向dev,切换到了dev上了。然后后面的修改都是在dev上了,master指针不变。

    image.png

    当我们在dev上把工作完成了,就可以合并分支。方法就是直接把master指向dev当前的提交。

    image.png

    下面是具体用命令怎么做

    • 创建dev分支并切换
    $ git branch dev
    $ git checkout dev#切换分支
    
    • 正常提交
    • 切换到master分支上
    • 合并指定分支dev当前master分支
    git merge dev
    

    此时有可能两个分支都有提交,所以无法自动合并,需要手动解决冲突,再提交


    image.png
    • 删除分支
    $ git branch -d dev
    

    分支策略

    在实际团队协作的时候,应该保证master非常稳定,只 是用来发布新的版本,平台应该不在上面修改。

    每个人可以经常生成一些dev分支, 在上面进行修改,当有必要的时候,再合并到主分支上即可。

    场景一:Bug分支

    每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。

    当你接到一个修复一个代号101的bug的任务时,可以创建一个分支issue-101来修复它,但是dev上的工作只进行到一半,还没法提交,怎么办?

    • 可以使用stash功能把现场存储起来,之后可以恢复
    git stash
    
    • 然后创建Bug分支,进行修复
    • 切换到master上,合并,删除分支
    • 现在应该回到dev分支继续干活了。恢复现场
      • git stash apply:恢复以后stash内容不删除,需要再使用git stash drop
      • git stash pop:恢复的时候同时把stash的内容也删除了。
        因为可能多次保存现场,所以可以先使用git stash list查看,然后恢复指定的stash
    $ git stash apply stash@{0}
    

    场景二:Feature分支

    开发一个新feature,最好新建一个分支,但是还没开发完的时候,收到通知取消此特性。

    此时当然直接删除就好,不过问题就在于分支还没有被合并,如果删除可以通过git branch -D <name>强行删除。

    使用标签

    发布一个版本的时候,可以先在版本库里面打一个tag。标签其实就是版本库的一个快照

    既然有commit,为什么还要tag呢?

    比如要将上周一的版本打包发布,我们知道commit id是一堆乱七八糟的数字,并不好查找,如果加上一个tag v1.2,就有了实际意义,可以与某个commit绑在一起,更好查找。

    如何打标签

    • 首先,切换到打标签的分支上git branch
    • 使用git tag v1.l0创建一个标签,使用git tag可以查看所有标签,标签不是按照时间排序,而是按照字母排序
    • 如果要绑定历史的 commit,可以怎能先使用git log找到commit id
    git tag v0.9  commit id 
    
    • 可以创建带有说明的标签
    git tag -a v0.1  -m "version 0.1 released"  32321332
    

    可以使用 git show v0.1查看说明。

    如果标签打错了,能改吗?当然能。删除即可。

    $ git tag -d v0.1
    

    因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。

    远程仓库

    到现在为止我们已经学会了如何在自己的电脑上进行工作,本章则将讲解如何把代码托管到Gitee远程仓库来进行管理,这样就可以进行协作以及代码的备份呢。

    之前我们只是在自己的电脑上搭一个Git仓库,实际上也可以分布到不同的机器上,别的机器只要复制原始版本就好了,这样就可以保证大家都一样。

    所以完全可以搭一个Git服务器,然后所有的人都从服务器里面复制一份到自己这边,再把各自的提交推送到仓库里面,实现协作。

    最著名的Git服务器当属GitHub,不过在国内比较的慢,所以我们使用中国版的GitHub——码云gitee.com

    上传公钥

    本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以需要先上传公钥,想知道原理可以点击HTTPS

    • 首先创建SSH Key
      打开CMDer,输入
     ssh-keygen -t rsa -C "youremail@example.com"#需要把邮件地址换成你自己的邮件地址
    

    然后一路回车
    可以通过everything搜索一下id_rsa.pub这个公钥在那里,然后使用Notepad++打开,复制所有的内容。

    image.png
    • 在Gitee的设置里面粘贴公钥的内容。
    image.png

    为什么要SSH Key呢?
    因为码云要识别这个推送确实是你本人干的。

    当然码云支持多个Key,如果有多个电脑,可以建立多个Key

    将代码推送到远端

    如果要把代码推送到远端,有两种场景,一是现在已经在本地建立了仓库了,现在想在Gitee上同样建立一个,然后合并即可。
    另一种是现在啥都没干,直接从Gitee上建一个,然后clone到本地即可。

    首先在Gitee上建立一个新仓库名字是articlespider


    image.png
    • 如果已经在本地建立了仓库
      image.png
      • 首先关联远程库:git remote add origin git@server-name:path/repo-name.git
      • 使用命令git push -u origin master第一次推送master分支的所有内容;
      • 此后的提交只需要使用git push origin master
    cd existing_git_repo
    git remote add origin https://gitee.com/***/articlespider.git
    git push -u origin master
    

    如果在新建远程仓库的时候加上了README.MD,但是这个Readme.md又不在本地库里面,所以会报错。可以

    $ git pull --rebase origin master
    

    当然也可以在本地根目录新建一个Readme.md

    • 如果现在还没有建立仓库,可以使用git clone复制一个版本下来。
    git clone git@gitee.com:****/articlespider.git
    

    多人协作

    创建了远程仓库以后,可以进行多人协作。可以将本地的分支推送到远端,也可以从远端拉取

    推送分支

    远程仓库默认名称是origin

    可以使用git push进行推送。

    git push origin 分支
    

    拉取分支

    现在另一个人需要在dev分支上做开发,首先应该先clone一份到本地。

    git clone git@gitee.com:****/articlespider.git
    

    当从远程仓库克隆的时候,Git自动把master与远程的master对应起来。

    查看远程库的信息git remote -v

    此时只能看到master分支,如果也要在分支dev上开发的话,必须创建远程origin的dev分支到本地,

    git checkout -b dev origin/dev
    

    然后就可以继续开发了。

    那么我们怎么与之协作呢?

    • 首先可以使用git push origin <branch>推送自己的修改
    • 如果推送失败,则远程分支比本地的更新,需要先用git pull合并。
      如果提示no tracking information,说明链接关系没有建立起来。使用
    git branch --set-upstream <branch> origin/<branch>
    
    • 如果合并有冲突,则解决冲突,并在本地提交
    • 冲突解决之后,再用git push origin <branch>

    推送标签

    因为创建的标签都只存储在本地,不会自动推送到远程

    如果要推送某个标签到远程,使用命令git push origin <tagname>
    或者,一次性推送全部尚未推送到远程的本地标签:

    $ git push origin --tags
    

    如果要删除的话,首先需要先删除本地的。

    $ git tag -d v0.9
    

    然后,从远程删除。

    $ git push origin :refs/tags/v0.9
    

    修改远程库的名字

    我们可能同时进行多个项目,他们都需要推送到远端。比如learngit项目,现在要与远程库关联

    git remote add origin git@gitee.com:<your name>/learngit.git
    

    如果报错fatal: remote origin already exists.说明本地库已经关联了一个名叫origin的远程库

    可以先删除

    git remote rm origin
    

    再关联一个远程库gitee

    git remote add gitee git@gitee.com:<gitee name>/learngit.git
    

    此时远程库的名称叫gitee,不叫origin。

    如果要推送:

    git push gitee master
    

    配置别名

    所谓配置别名其实就是配置命令的简写,比如使用git st表示git status等。

    $ git config --global alias.st status#查看工作区状态
    $ git config --global alias.co checkout#切换分支,撤销修改
    $ git config --global alias.ci commit#提交
    $ git config --global alias.br branch#分支
    $ git config --global alias.unstage 'reset HEAD'#回退
    $ git config --global alias.last 'log -1'#查看log
    $git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
    

    加上--global是针对当前用户起作用的

    搭建Git服务器

    搭建服务器

    需要准备一台运行Ubuntu的机器

    • 安装git :sudo apt-get install git
    • 创建git 用户,用来运行git服务:sudo adduser git
    • 创建证书登录
      收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。
    • 初始化git仓库
      选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:
    $ sudo git init --bare sample.git
    

    这样就会创建一个没有工作区的裸仓库,把所有者改为git

    sudo chown -R git:git sample.git
    
    • 禁用shell登录
      编辑/etc/passwd文件完成。找到类似下面的一行:
    git:x:1001:1001:,,,:/home/git:/bin/bash
    

    改为:

    git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
    

    这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。

    • 克隆远程仓库:
    $ git clone git@server:/srv/sample.git
    

    总结

    最后把所有的命令总结成一个表格

    一级 二级 命令 备注
    提交代码 新建仓库 git init
    提交到暂存区 git add .
    提交到分支 git commit -m ""
    查看 查看状态 git status
    查看提交记录 git log --pretty=oneline 可以看到commit id
    查看命令历史 git reflog 可以看到未来版本
    对比 git diff HEAD -- readme.txt
    标签 git tag
    远端仓库 git remote -v
    版本控制 未提交到暂存区 git checkout .
    已提交到暂存区 git reset HEAD file
    已经提交到分支 git reset --hard <HEAD^>
    分支 创建分支 git branch dev
    切换分支 git checkout dev
    合并 git merge dev 将dev分支合并到当前分支上
    删除分支 git branch -d dev
    强行删除 git branch -D dev 还没合并就要提前删除
    存储现场 git stash 然后切换到另一个分支干活
    恢复现场 git stash pop
    标签 创建标签 git tag v0.9
    删除标签 git tag -d v0.8
    推送远程标签 git push origin --tags
    删除远程标签 git push origin :refs/tags/v0.9
    远程仓库 上传公钥 ssh-keygen -t rsa -C "youremail@example.com"
    关联远程库 git remote add origin https://gitee.com/***/articlespider.git
    删除远程库 git remote rm origin
    第一次提交 git push -u origin master
    普通提交 git push origin
    拉取 git pull origin
    多人协作 复制 git clone git@gitee.com:****/articlespider.git
    创建远端分支到本地 git checkout -b dev origin/dev
    创建链接关系 git branch --set-upstream origin/
    别名 查看log $git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)

    参考

    本文主要是根据Git教程整理得到的,目的是帮助Git学习。

    相关文章

      网友评论

          本文标题:git教程笔记

          本文链接:https://www.haomeiwen.com/subject/eglmzxtx.html