一篇博客让你搞懂 Git 的简单用法

771 阅读9分钟

古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 —— 苏轼

先说概念

Git 是目前最火的版本控制软件,在我们学习 Git 之前我们先来了解一下 软件版本控制的概念。

软件版本控制是什么

版本控制软件提供了完备的版本管理功能,用于存储、追踪目录(文件夹)和文件的修改历史,是软件开发者必备工具,是软件公司的基础设施。版本控制软件的最高目标,是支持软件公司的配置管理活动,追踪多个版本的开发和维护活动,及时发布软件。其主要功能有:

  • 集中管理档案,安全授权机制:档案集中地存放在服务器上,经系统管理员授权给各个用户。用户通过 check incheck out 的方式访问服务器上的文件,未经授权的用户则无法访问服务器上的文件。
  • 软件版本升级管理: 每次登陆时,在服务器上都会生成新的版本,任何版本都可以随时检出编辑。
  • 加锁功能:在文件更新时保护文件,避免不同的用户更改同一文件是发生冲突。
  • 提供不同版本源程序的比较。

版本控制系统分为三大类:本地版本控制系统,集中式版本控制系统和分布式版本控制系统

本地版本控制系统

本地版本控制是将文件的各个版本存放在磁盘,使用这种方式在已经程度上解决了手动复制粘贴的问题,但无法解决多人协作的问题。

本地版本控制系统

集中式版本控制系统

集中式版本控制系统的版本库集中放置在中央服务器中。开发人员需要先从版本控制中央服务器获取最新版的内容,开发工作完成后,需要再将本地内容提交给版本控制中央服务器。 集中式版本控制系统最大的毛病就是必须联网才能工作。如果是局域网还好,带宽够大,速度够快。可是如果是互联网的话,受到带宽的限制。分布式版本控制

集中式版本控制系统

分布式版本控制系统

和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个开发人员电脑里都有完整的版本库,某一个开发人员的电脑坏掉了不要紧,随便从其他开发人员那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有开发人员都没法工作。

分布式版本控制系统

Git 概述

Git 是目前世界上最优秀的软件版本控制系统。Git 是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理。

Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper ,后者之前一直是 Linux 内核开发人员在全球使用的主要源代码工具。

尽管最初Git的开发是为了辅助 Linux 内核开发的过程,但是已经发现在很多其他自由软件项目中也使用了 Git。

Git官方如下

Git官方

Git 的特点

  • 分支更快、更容易。
  • 支持离线工作;本地提交可以稍后提交到服务器上。
  • Git 提交都是原子的,且是整个项目范围的,而不像 CVS 中一样是对每个文件的。
  • Git 中的每个工作树都包含一个具有完整项目历史的仓库。
  • 没有哪一个 Git 仓库会天生比其他仓库更重要。

Git 配置

Git 的客户端在进行安装完之后需要进行一些配置,配置命令如下所示:

git config --global user.name "你的名字"
git config --global user.email 你的邮箱

# 例如
git config --global user.name "is_sweet"
git config --global user.email "is_sweet@163.com"

因为 Git 是分布式版本控制系统,所以每一台电脑注册用户信息(名称和 Email 地址)。

值得注意的是,git config 命令的 --global 参数,表示当前这台电脑上所有的 Git 仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和 Email 地址。

Git 操作

工作区、暂存区和版本库

  • 工作区:就是你在电脑里能看到的目录。
  • 暂存区:英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
  • 版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。

如下图展示三者之间的关系:

工作区、暂存区和版本库的关系

创建仓库

创建仓库分为两种方式,分别是创建一个新的仓库,另一种方式是克隆一个已有的仓库。

git init

git init 命用于在目录中创建一个新的 Git 仓库。Git 的很多命令都需要在 Git 的仓库中运行,所以 git init 是使用 Git 的第一个命令。

示例代码如下所示:

is_sweet@Sweet MINGW64 /b/Practice code
$ mkdir is_sweet	# 创建文件夹

is_sweet@Sweet MINGW64 /b/Practice code
$ cd is_sweet/		# 切换目录

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet
$ git init			# 创建 Git 仓库
Initialized empty Git repository in B:/Practice code/is_sweet/.git/

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ ls -a				# 查看是否创建成功
.  ..  .git

在执行完成 git init 命令后,Git 仓库会生成一个 .git 目录,该目录包含了资源的所有元数据,其他的项目目录保持不变。

现在我们已经创建好了这个 Git 本地仓库,有了这个本地仓库,我们还需要在代码托管平台创建一个仓库,这里以 GitHub 为例,我们创建一个仓库,账号注册这里就不做赘述了,

点击 New repository 按钮会弹出如下界面

在这里插入图片描述

这里是创建仓库需要的信息,如下所示

在这里插入图片描述

点击 Create repository 创建这个仓库,创建完仓库之后我们可以得到这个仓库的地址,地址有两种方式分别是

HTTPS

https://github.com/Is-Sweet/test.git

SSH

git@github.com:Is-Sweet/test.git

我们在我们的本地新建一个 README.md 文件,写入123321

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ touch README.md	# 新建文件
is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ vi README.md		# 编辑文件

现在我们就将我们新建的仓库推送到这个 GitHub 仓库上,代码如下所示:

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git add README.md		# 1. 将文件添加的 Git 的缓冲区
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git commit -m "这是第一个文件"	# 2. 从Git的暂存区提交版本到仓库,参数-m后为当次提交的备注信息
[master (root-commit) e1246ac] 这是第一个文件
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git remote add test https://github.com/Is-Sweet/test.git	# 3. 添加远程版本库	

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git push -u test master	# 4. 将本地的Git仓库信息推送上传到服务器 master 分支,这里可能会弹出如下界面,输入账号密码即可
Logon failed, use ctrl+c to cancel basic credential prompt.
# 5. 输入账号密码
Username for 'https://github.com': Is-Sweet
Password for 'https://Is-Sweet@github.com':
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 248 bytes | 248.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/Is-Sweet/test.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'test'.

在这里插入图片描述

git clone

我们可以直接使用 git clone 从现有 Git 仓库中拷贝项目。

语法结构如下所示:

git clone <repo> <directory>

参数说明:

  • repo**:** Git 仓库。
  • directory: 本地目录。

这里我们将我们新建的那个 GitHub 仓库 克隆到本地,示例代码如下所示:

is_sweet@Sweet MINGW64 /b/Practice code
$ git clone https://github.com/Is-Sweet/test.git	# 克隆 Git 仓库 这里还会让你登陆 用户
Cloning into 'test'...
Logon failed, use ctrl+c to cancel basic credential prompt.
Username for 'https://github.com': Is-Sweet
Password for 'https://Is-Sweet@github.com':
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 228 bytes | 1024 bytes/s, done.

is_sweet@Sweet MINGW64 /b/Practice code
$ ls
is_sweet   test

is_sweet@Sweet MINGW64 /b/Practice code
$ cd test

is_sweet@Sweet MINGW64 /b/Practice code/test (master)
$ ls
README.md

is_sweet@Sweet MINGW64 /b/Practice code/test (master)
$ cat README.md
# 123321

这里创建仓库的两种方式已经介绍完了。

Git 的基础操作

提交与修改

Git 的提交与修改主要通过以下几个命令来完成的,如下表所示

命令说明
git add添加一个或多个文件到暂存区
git status查看仓库当前的状态,显示有变更的文件。
git diff比较文件的不同,即暂存区和工作区的差异。
git commit提交暂存区到本地仓库。
git reset回退版本。
git rm删除工作区文件。
git mv移动或重命名工作区文件。

示例代码如下所示:

is_sweet@Sweet MINGW64 /b/Practice code/test (master)
$ touch file{1..10}.txt	 # 创建文件

is_sweet@Sweet MINGW64 /b/Practice code/test (master)
$ ls		# 验证是否创建成功
README.md  file10.txt  file3.txt  file5.txt  file7.txt  file9.txt
file1.txt  file2.txt   file4.txt  file6.txt  file8.txt

# git add 语法结构如下所示:
# git add [file1] [file2] 或者 git add [dir]
is_sweet@Sweet MINGW64 /b/Practice code/test (master)
$ git add .	

# 查看在你上次提交之后是否有对文件进行再次修改。
is_sweet@Sweet MINGW64 /b/Practice code/test (master)
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   file1.txt
        ...

# 使用 -s 参数来获得简短的输出结果:
is_sweet@Sweet MINGW64 /b/Practice code/test (master)
$ git status -s
A  file1.txt
....

# 将暂存区内容添加到本地仓库中
# 语法结构 git commit [file1] [file2] ... -m [message]
# -a 参数设置修改文件后不需要执行 git add 命令,直接来提交
is_sweet@Sweet MINGW64 /b/Practice code/test (master)
$ git commit -m '提交'

远程操作

远程操作仓库的常用指令如下所示:

命令说明
git remote远程仓库操作
git pull下载远程代码并合并
git push上传远程代码并合并

git remote 命令

git remote -v	# 显示所有远程仓库:
git remote show [remote]	# 显示某个远程仓库的信息:
git remote add [shortname] [url] # 添加远程版本库:
git remote rm name  # 删除远程仓库
git remote rename old_name new_name  # 修改仓库名

git push 命令

git push <远程主机名> <本地分支名>:<远程分支名>
# 如果本地分支名与远程分支名相同,则可以省略冒号:
git push <远程主机名> <本地分支名>
# 例如
git push origin master:master

git pull 命令

git pull <远程主机名> <远程分支名>:<本地分支名>
# 实例
is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git pull test master	# 如果远程分支是与当前分支合并,则冒号后面的部分可以省略。

Git 分支管理

几乎每一种版本控制系统都以某种形式支持分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。

有人把 Git 的分支模型称为必杀技特性,而正是因为它,将 Git 从版本控制系统家族里区分出来。

到目前的操作,我们的 Git 仓库中只有一个分支,这个分支在 Git 中也叫主分支,也就是 master 分支。

查看、创建、切换分支和更新内容

查看分支命令

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git branch
* master

创建分支命令

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git branch myMaster	# git branch (branchname)

切换分支命令

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (myMaster)
$ git checkout myMaster
Already on 'myMaster'	# git checkout (branchname)

修改某个文件并推送

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (myMaster)
$ vi test1.txt

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (myMaster)
$ git add test1.txt			# 提交到暂存区
warning: LF will be replaced by CRLF in test1.txt.
The file will have its original line endings in your working directory

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (myMaster)
$ git status				# 查看暂存区内容
On branch myMaster
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   test1.txt


is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (myMaster)
$ git commit -m 'test'		# 提交到本地仓库
[myMaster 6bdd4fc] test
 1 file changed, 1 insertion(+)

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (myMaster)
$ git push test myMaster	# 推送到服务器
Logon failed, use ctrl+c to cancel basic credential prompt.
Username for 'https://github.com': Is-Sweet
Password for 'https://Is-Sweet@github.com':
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 257 bytes | 257.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
remote:
remote: Create a pull request for 'myMaster' on GitHub by visiting:
remote:      https://github.com/Is-Sweet/test/pull/new/myMaster
remote:
To https://github.com/Is-Sweet/test.git
 * [new branch]      myMaster -> myMaster

合并分支

在 Git 中使用 git merge 命令用来合并分支,示例代码如下所示:

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (myMaster)
$ git checkout master	# 切换分支
Switched to branch 'master'
Your branch is up to date with 'test/master'.

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git merge myMaster # 合并 myMaster 到当前分支
Updating b682387..6bdd4fc
Fast-forward
 test1.txt | 1 +
 1 file changed, 1 insertion(+)

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git branch -d myMaster	# 删除分支
Deleted branch myMaster (was 6bdd4fc).

is_sweet@Sweet MINGW64 /b/Practice code/is_sweet (master)
$ git branch			# 查看结果
* master

关于分支的一些命令

# 列出所有本地分支
$ git branch

# 列出所有远程分支
$ git branch -r

# 列出所有本地分支和远程分支
$ git branch -a

# 新建一个分支,但依然停留在当前分支
$ git branch [branch-name]

# 新建一个分支,并切换到该分支
$ git checkout -b [branch]

# 新建一个分支,指向指定commit
$ git branch [branch] [commit]

# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]

# 切换到指定分支,并更新工作区
$ git checkout [branch-name]

# 切换到上一个分支
$ git checkout -

# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]

# 合并指定分支到当前分支
$ git merge [branch]

# 选择一个commit,合并进当前分支
$ git cherry-pick [commit]

# 删除分支
$ git branch -d [branch-name]

# 删除远程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]

写在最后

这篇博客介绍了 Git 的基本用法,Git 是我们在以后的开发中必备的机能,此篇博客也仅仅是 GIt 的入门。