git教程笔记

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学习。

posted @ 2018-02-04 11:51  dy2903  阅读(232)  评论(0编辑  收藏  举报