Git学习(一)
一、版本控制的发展
本地版本控制系统->集中式版本控制系统->分布式集中控制系统
本地版本控制系统:
早期为了方便查找历史版本,而推出版本控制
最流行的一种叫做RCS
,现今许多计算机系统上都还看得到它的踪影。RCS
的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
缺点:无法在不同系统上的开发者协同工作
集中式版本控制系统
可以由多个客户机访问这个服务器,进行协同操作
缺点:
- 如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作
- 如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。
代表:CVS
、Subversion
以及Perforce
分布式集中控制系统
优点:客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
代表:Git
、Mercurial
、Bazaar
以及Darcs
二、Git的诞生
2.1 Git 诞生的背景
同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。
Linus 在1991年创建了开源的 Linux,从此,Linux 系统不断发展,已经成为最大的服务器系统软件了。在1991-2002年期间,世界各地的志愿者把源代码文件通过 diff 的方式发给 Linus,然后由 Linus 本人通过手工方式合并代码。
你也许会想,为什么 Linus 不把 Linux 代码放到版本控制系统里呢?不是有CVS、SVN这些免费的版本控制系统吗?因为Linus 坚定地反对CVS和SVN,这些集中式的版本控制系统不但速度慢,而且必须联网才能使用。有一些商用的版本控制系统,虽然比CVS、SVN好用,但那是付费的,和 Linux 的开源精神不符。
2.2 Linus 两周完成 Git
到 2002 年,Linux 系统已经发展了十年了,代码库之大让 Linus 很难继续通过手工方式管理了,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码,BitKeeper 的东家 BitMover 公司也免费授权 Linux 社区使用这个版本控制系统。后来 BitMover 公司发现社区有人试图破解 BitKeeper 的协议,于是 BitMover 公司收了回 Linux 社区的免费使用权。
这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。 他们对新的系统制订了若干目标:
- 速度
- 简单的设计
- 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
- 完全分布式
- 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)
于是,Linus 花了两周时间自己用 C 写了一个分布式版本控制系统,这就是 Git!一个月之内,Linux 系统的源码已经由 Git 管理了!
2.3 Git 的发展壮大
自 2005 年诞生以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。Git 迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub 网站上线了,它为开源项目免费提供 Git 存储,无数开源项目开始迁移至 GitHub ,包括jQuery
,PHP
,Ruby
等等。
2.4 CODE CHINA
GitCode
CODE CHINA 使用手册
三、Git的安装
3.1 Windows下安装
3.2 Git GUI,Git Bash,Git CMD之间的区别
3.2.1 Git Bash
Bash,Unix shell的一种,Linux与Mac OS X v10.4都将它作为默认shell。
Git Bash就是一个shell,是Windows下的命令行工具,可以执行Linux命令。
Git Bash是基于CMD的,在CMD的基础上增添一些新的命令与功能。所以建议在使用的时候,用Bash更加方便。
3.2.2 Git CMD
(命令行提示符)是Windows操作系统上的命令行解释程序。当你在Windows上安装git并且习惯使用命令行时,可以使用cmd来运行git命令。
3.2.3 Git GUI
基本上针对那些不喜欢黑屏(即命令行)编码的人。它提供了一个图形用户界面来运行您喜欢的git命令。
四、Git的一些命令
4.1 config
$ git config --global user.name "李老师"
$ git config --global user.email li@csdn.net
4.1.1 检查某项配置
git config <key>
$ git config user.name
李老师
4.1.2 配置命令颜色
$ git config --global color.ui true
4.2 忽略特殊文件
.gitignore
在Git 工作区的根目录下创建一个特殊的 .gitignore
文件
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
# My configurations:
db.ini
deploy_key_rsa
4.2.1 强制添加被忽略的文件
遇到添加一个文件到 Git,但发现添加不了,原因是这个文件被.gitignore忽略了:
$ git add App.class
The following paths are ignored by one of your .gitignore files:
App.class
Use -f if you really want to add them.
如果你确实想添加该文件,可以用-f强制添加到 Git:
$ git add -f App.class
4.2.2 检查忽略规则
git check-ignore
$ git check-ignore -v App.class
.gitignore:3:*.class App.class
Git会告诉我们,.gitignore
的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
4.2.3 添加例外规则
# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class
# 不排除.gitignore和App.class:
!.gitignore
!App.class
4.3 配置别名
除了通过 配置忽略文件 来提高git commit 时的便捷性外,Git 中还有一种可以让大家在敲入 Git 命令时偷懒的办法——那就是配置 Git 别名。
4.3.1 配置 git status/commit/checkout/branch
$ 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 ci -m “sth.”
4.3.2 配置 git reset HEAD file
再比如git reset HEAD file
命令,他可以把暂存区的修改撤销掉(unstage),重新放回工作区。既然是一个unstage
操作,就可以配置一个unstage
别名:
$ git config --global alias.unstage ‘reset HEAD’
当你敲入命令:
$ git unstage test.py
实际上 Git 执行的是:
$ git reset HEAD test.py
4.3.3 配置 git log -1
配置一个git last,让其显示最后一次提交信息:
$ git config --global alias.last ‘log -1’
这样,用git last就能显示最近一次的提交:
$ git last
commit 4aac6c7ee018f24d2dabfd01a1e09c77612e1a4e (HEAD -> master)
Author: Miykael_xxm xiongjiamu@gmail.com
Date: Tue Nov 17 11:14:15 2020 +0800
branch test
4.3.4 配置 git lg
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"
4.4 配置文件
4.4.1 全局配置文件
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@codechina.csdn.net:codechina/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1
别名就在[alias]后面,要删除别名,直接把对应的行删掉即可。
而当前用户的 Git 配置文件放在用户主目录下的一个隐藏文件.gitconfig
中:
4.4.2 用户配置文件
$ cat .gitconfig
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = your@email.com
[color]
ui = true
配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置。
五、Git使用
5.1 创建仓库: git init / git clone
5.1.1 创建目录
mkdir(创建目录),cd(进入路径),pwd(显示绝对路径)
5.1.2 初始化仓库
git init
通过git init命令把这个目录变成 Git 可以管理的仓库
5.1.3 克隆仓库
git clone https://codechina.csdn.net/codechina/help-docs
这会在当前目录下创建一个名为 help-docs
的目录,并在这个目录下初始化一个.git
文件夹, 从远程仓库拉取下所有数据放入.git
文件夹,然后从中读取最新版本的文件的拷贝。 如果你进入到这个新建的help-docs
文件夹,你会发现所有的项目文件已经在里面了,准备就绪等待后续的开发和使用。
5.1.4 自定义本地仓库名称
git clone https://codechina.csdn.net/codechina/help-docs mydocs
目录名变为了mydocs
Git 支持多种数据传输协议。 上面的例子使用的是 https://
协议,不过你也可以使用 git://
协议或者使用 SSH
传输协议,比如 user@server:path/to/repo.git
5.2 添加文件: git add / git commit
5.2.1 文件添加到仓库
git add readme.txt
5.2.2 文件提交到仓库
$ git commit -m “wrote a readme file”
这里简单解释一下git commit
命令,-m
后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
- 1 file changed:1个文件被改动(我们新添加的readme.txt文件)
- 2 insertions:插入了两行内容(readme.txt有两行内容)
为什么 Git 添加文件需要add
,commit
一共两步呢?因为commit
可以一次提交很多文件,所以你可以多次add不同的文件,比如:
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."
5.3 查看修改: git status / git diff
5.3.1 获取状态
当你修改
readme.txt
文件时,用git status
来获取状态
5.3.2 比较修改内容
git diff
这个命令查看相较于上一次暂存都修改了些什么内容了
知道了对readme.txt作了什么修改后,再把它提交到仓库就放心多了,提交修改和提交新文件是一样的两步,第一步是git add:
$ git add readme.txt
同样没有任何输出。在执行第二步git commit之前,我们再运行git status看看当前仓库的状态:
$ git status
On branch master
Changes to be committed:
(use “git reset HEAD …” to unstage)
modified: readme.txt
git status告诉我们,将要被提交的修改包括readme.txt,下一步,就可以放心地提交了:
$ git commit -m “add distributed”
[master e55063a] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
提交后,我们再用git status命令看看仓库的当前状态:
$ git status
On branch master
nothing to commit, working tree clean
Git告诉我们当前没有需要提交的修改,而且,工作目录是干净(working tree clean)的。
5.4 恢复文件: git log / git reset
5.4.1 查看全部commit命令
git log
简约点:--pretty=oneline
git log --pretty=oneline
可以取别名git lg
5.4.2 退回到历史版本
- e55063a - (HEAD -> master) add distributed (4 minutes ago) <Miykael_xxm>
- 50ed06b - wrote a readme file (6 minutes ago) <Miykael_xxm>
Git 必须知道当前版本是哪个版本,在 Git 中,用HEAD
表示当前版本,也就是最新的提交e55063a
,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100
。
git reset --hard HEAD^
很快,仅仅是将指针移动
5.4.3 移动HEAD指针
gitreflog
Git 提供了一个命令git reflog
用来记录你的每一次命令,当你用git reset --hard HEAD^
回退到wrote a readme file
版本时,再想恢复到add distributed
,就可以通过git reflo
g命令找到add distributed
的commit id
。
从上面的输出可以看到,add distributed
的commit id
是e55063a
,现在,我们就可以通过 git reset --hard e55063a
切换到最新的版本上了