Git 是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种项目。
Git 易于学习,占地面积小,性能极快。 它具有廉价的本地库,方便的暂存区域和多个工作流分支等特性。其性能优于 Subversion、CVS、Perforce 和 ClearCase 等版本控制工具。
版本控制是一种记录文件内容变化,以便将来查阅特定版本修订情况的系统。利用版本控制工具,可以记录文件修改历史记录,从而让用户能够查看历史版本,避免版本混乱,方便版本切换;此外,可以提高团队协作能力和开发效率,大家可以及时获取到最新的代码。
版本控制系统的整个发展可以分为如下三个阶段:
1)本地版本控制系统
许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。
为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。
其中最流行的一种叫做 RCS(一个针对单独文件的版本管理工具),现今许多计算机系统上都还看得到它的踪影。 RCS 的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
2)集中化的版本控制系统
接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作? 于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。 这类系统,诸如 CVS
、SVN(Subversion)
以及 Perforce
等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。
这种做法带来了许多好处,特别是相较于老式的本地 VCS
来说。 现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。
但这么做也有一个显而易见的缺点,那就是是中央服务器的单点故障。
本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。
- CVS
CVS(Concurrent Versions System)诞生于1985年,由荷兰阿姆斯特丹VU大学的Dick Grune教授设计实现。Dick Grune教授和两个学生共同开发一个项目,由于三人工作时间无法协调,急需一个记录和协同开发的软件。于是Dick Grune教授通过脚本语言对RCS(单文件版本管理工具)进行了封装修改,设计出有史以来第一个被大规模使用的版本控制工具CVS。关于这段历史,大佬曾在网站上留下这样的话:
“在1985年的一个糟糕的秋日里,我在校汽车站等车回家,脑海里一直纠结着一件事一如何处理RCS文件、用户文件(工作区)和Entries 文件的复杂关系,有的文件可能会缺失、冲突、删除,等等。我的头有些晕了,于是决定画一个大表,将复杂的关联画在其中,看看出来的结果是什么样的…”
CVS的成功引发了版本控制系统的爆发,各种版本控制系统相继被开发出来,其中比较典型的系统就是SVN(Subversion)。
1986年Dick通过新闻组发布了CVS,1989年Brian Berliner用C语言将CVS进行了重写。
- Subversion
由于其命令行工具名为svn,因此通常被简称为SVN。由CollabNet公司于2000年资助并开始开发,目的是创建一个更好用的版本控制系统以取代CVS。SVN的前期由CVS做版本管理,到2001年,开始用于自己的版本控制。
3)分布式版本控制系统
于是分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。 在这类系统中,像 Git
、Mercurial
、Bazaar
以及 Darcs
等,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
不仅如此,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。这样一来,你就可以在同一个项目中,分别和不同工作小组的人相互协作。 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。
分布式的版本控制系统出现之后,解决了集中式版本控制系统的缺陷:
服务器断网的情况下也可以进行开发(因为版本控制是在本地进行的)
每个客户端保存的也都是整个完整的项目(包含历史记录,更加安全)
$ git help
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
[--super-prefix=<path>] [--config-env=<name>=<envvar>]
<command> [<args>]
These are common Git commands used in various situations:
start a working area (see also: git help tutorial)
clone Clone a repository into a new directory
init Create an empty Git repository or reinitialize an existing one
work on the current change (see also: git help everyday)
add Add file contents to the index
mv Move or rename a file, a directory, or a symlink
restore Restore working tree files
rm Remove files from the working tree and from the index
examine the history and state (see also: git help revisions)
bisect Use binary search to find the commit that introduced a bug
diff Show changes between commits, commit and working tree, etc
grep Print lines matching a pattern
log Show commit logs
show Show various types of objects
status Show the working tree status
grow, mark and tweak your common history
branch List, create, or delete branches
commit Record changes to the repository
merge Join two or more development histories together
rebase Reapply commits on top of another base tip
reset Reset current HEAD to the specified state
switch Switch branches
tag Create, list, delete or verify a tag object signed with GPG
collaborate (see also: git help workflows)
fetch Download objects and refs from another repository
pull Fetch from and integrate with another repository or a local branch
push Update remote refs along with associated objects
'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help ' or 'git help '
to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.
命令 | 作用 |
---|---|
git config |
设置用户签名git config --global user.name 用户名 git config --global user.email 邮箱 |
git init |
初始化本地库 |
git status |
查看本地库状态 |
git add 文件名 |
添加到暂存区 |
git commit -m "日志信息" 文件名 |
提交到本地库 |
git reflog |
查看历史记录 |
git reset --hard 版本号 |
版本穿梭 |
(1)设置用户签名
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop
$ git config --global user.name 'JustRight'
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop
$ git config --global user.email '[email protected]'
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop
$ cat ~/.gitconfig
[user]
name = JustRight
email = 252940120@qq.com
签名的作用是区分不同操作者身份。用户的签名信息在每一个版本的提交信息中能够看到,以此确认本次提交是谁做的。Git 首次安装必须设置一下用户签名,否则无法提交代码。
注意:这里设置用户签名和将来登录 GitHub(或其他代码托管中心)的账号没有任何关系。git config还有很多其他的用途,比如可以用来取别名
git config --system alias.ci commit
(2)初始化本地库
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop
$ cd git-demo
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo
$ git init
Initialized empty Git repository in C:/Users/25294/Desktop/git-demo/.git/
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ ls -a
./ ../ .git/
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ tree -a
.
`-- .git
|-- HEAD
|-- config
|-- description
|-- hooks
| |-- applypatch-msg.sample
| |-- commit-msg.sample
| |-- fsmonitor-watchman.sample
| |-- post-update.sample
| |-- pre-applypatch.sample
| |-- pre-commit.sample
| |-- pre-merge-commit.sample
| |-- pre-push.sample
| |-- pre-rebase.sample
| |-- pre-receive.sample
| |-- prepare-commit-msg.sample
| |-- push-to-checkout.sample
| `-- update.sample
|-- info
| `-- exclude
|-- objects
| |-- info
| `-- pack
`-- refs
|-- heads
`-- tags
9 directories, 17 files
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
初始化的效果,生成
.git
目录,它就是Git的版本库为了查看目录结构,这里安装了tree命令。安装方法
- 打开进入 Tree for Windows 页面,选择下载
tree-版本-bin.zip
文件下载- 将压缩包中bin目录下的tree.exe复制到Git安装目录下的
usr\bin
目录即可Git从版本1.65开始,可以在
git init
命令后面直接输入目录名,自动完成目录 的创建
(3) 新增文件
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ vi hello.py
a = 1
b = 2
print(a + b)
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
No commits yet
Untracked files:
(use "git add ..." to include in what will be committed)
hello.py
nothing added to commit but untracked files present (use "git add" to track)
添加文件后再查看状态,检测到了未追踪的文件
hello.py
(4) 添加暂存区
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git add hello.py
warning: LF will be replaced by CRLF in hello.py.
The file will have its original line endings in your working directory
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached ..." to unstage)
new file: hello.py
(5)提交本地库
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git commit -m "first commit" hello.py
warning: LF will be replaced by CRLF in hello.py.
The file will have its original line endings in your working directory
[master (root-commit) be08904] first commit
1 file changed, 3 insertions(+)
create mode 100644 hello.py
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
nothing to commit, working tree clean
注意,Git提交时,一定要添加提交说明。
(6)修改文件
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ vi hello.py
a = int(input('please input the first number>'))
b = int(input('please input the second number>'))
print(a+b)
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified: hello.py
no changes added to commit (use "git add" and/or "git commit -a")
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git add hello.py
warning: LF will be replaced by CRLF in hello.py.
The file will have its original line endings in your working directory
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged ..." to unstage)
modified: hello.py
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git commit -m "second commit" hello.py
warning: LF will be replaced by CRLF in hello.py.
The file will have its original line endings in your working directory
[master b1bbedb] second commit
1 file changed, 3 insertions(+), 3 deletions(-)
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
nothing to commit, working tree clean
(7)历史版本
查看版本信息
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git reflog
b1bbedb (HEAD -> master) HEAD@{0}: commit: second commit
be08904 HEAD@{1}: commit (initial): first commit
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git log
commit b1bbedba2f67d0e96014c25043a6757010e12863 (HEAD -> master)
Author: JustRight <252940120@qq.com>
Date: Wed Jun 1 22:46:36 2022 +0800
second commit
commit be08904691a3c63d19e75f4a0e2d5dded2dd5cc6
Author: JustRight <252940120@qq.com>
Date: Wed Jun 1 22:38:00 2022 +0800
first commit
版本穿梭
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git reset --hard be08904
HEAD is now at be08904 first commit
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ vi hello.py
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ cat hello.py
a = 1
b = 2
print(a + b)
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git reflog
be08904 (HEAD -> master) HEAD@{0}: reset: moving to be08904
b1bbedb HEAD@{1}: commit: second commit
be08904 (HEAD -> master) HEAD@{2}: commit (initial): first commit
在版本控制过程中,同时推进多个任务,为每个任务,我们就可以创建每个任务的单独分支。使用分支意味着程序员可以把自己的工作从开发主线上分离开来,开发自己分支的时候,不会影响主线分支的运行。对于初学者而言,分支可以简单理解为副本。
使用分枝的好处:
常用命令:
$ git branch -h
usage: git branch [] [-r | -a] [--merged] [--no-merged]
or: git branch [] [-f] [--recurse-submodules] []
or: git branch [] [-l] [...]
or: git branch [] [-r] (-d | -D) ...
or: git branch [] (-m | -M) []
or: git branch [] (-c | -C) []
or: git branch [] [-r | -a] [--points-at]
or: git branch [] [-r | -a] [--format]
Generic options
-v, --verbose show hash and subject, give twice for upstream branch
-q, --quiet suppress informational messages
-t, --track[=(direct|inherit)]
set branch tracking configuration
-u, --set-upstream-to
change the upstream info
--unset-upstream unset the upstream info
--color[=] use colored output
-r, --remotes act on remote-tracking branches
--contains print only branches that contain the commit
--no-contains
print only branches that don't contain the commit
--abbrev[=] use digits to display object names
Specific git-branch actions:
-a, --all list both remote-tracking and local branches
-d, --delete delete fully merged branch
-D delete branch (even if not merged)
-m, --move move/rename a branch and its reflog
-M move/rename a branch, even if target exists
-c, --copy copy a branch and its reflog
-C copy a branch, even if target exists
-l, --list list branch names
--show-current show current branch name
--create-reflog create the branch's reflog
--edit-description edit the description for the branch
-f, --force force creation, move/rename, deletion
--merged print only branches that are merged
--no-merged print only branches that are not merged
--column[=