共计 8614 个字符,预计需要花费 22 分钟才能阅读完成。
这是一份扼要厄要的 Git 入门指南,如果你想疾速学会 Github,这篇文章是一个不错的抉择。
集体总结,如有不妥之处,敬请指出。
目录
版本库的创立
- Git 的装置
- 版本库的创立
版本库的操作
- 文件操作
- 版本回退
- 批改撤销
近程库连贯
- 近程库增加与解除
- 从近程库克隆
分支治理
- 创立与合并分支
- 多人合作
标签治理
- 创立标签
- 操作标签
版本库的创立
Git 的装置
在 Ubuntu Linux 上应用 apt 软件包管理工具进行装置
sudo apt-get install git
在 windows 上间接进入 Git 官网下载安装程序,而后依照默认选项装置即可
版本库的创立
抉择一个适合的地位利用 mkdir 指令创立一个空目录,而后进入后输出指令
git init
于是该目录就变成了 Git 能够治理的仓库,仔细的读者能够发现当前目录下多了一个 .git
的目录,这个目录是 Git 来跟踪治理版本库的,没事千万不要手动批改这个目录外面的文件,不然改乱了,就把 Git 仓库给毁坏了。
版本库的操作
文件操作
在文件操作之前首先明确几个概念
工作区
就是电脑中能间接看见的目录
版本库
工作区目录中有一个暗藏目录.git。这个是 Git 的版本库,版本库次要由两个局部组成,stage 暂存区和分支区。
将文件增加至 Git 版本库中时,有三个步骤:
首先 在工作区创立一个文件 Read.txt
vim/typora Read.txt
将文件批改增加至暂存区,在增加至暂存区前,咱们首先看一下 git 的状态
~/CS61A$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
Read.txt
nothing added to commit but untracked files present (use "git add" to track)
Git 分明的通知咱们,有一个文件呈现了,而 Read.txt
还素来没有被增加过,所以它的状态是Untracked
。
而后 咱们创立文件这次操作增加至暂存区
git add Read.txt
如果增加的是文件夹能够应用
git add vs/*
如果想删除文件能够用
git rm Read.txt
再次查看 git 的状态
~/CS61A$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: Read.txt
Changes to be committed
咱们发现 git 曾经辨认了这个文件,可见这个文件曾经被增加到了暂存区。
最初 咱们将文件创建这次操作提交至仓库的 master 分支(分支的概念前面会讲到)
git commit Read.txt -m "commit"
如果想提交全副文件的操作能够用
git commit -m "commit"
这里的 - m 参数是对这次提交进行文字说明
再次查看 git 的状态
~/CS61A$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
可见此时暂存区为空,批改已提交至仓库
咱们能够将创立文件并提交至仓库的过程用流程图示意
graph LR
A[在工作区创立文件]===>B[将批改 / 创立 / 删除操作增加至暂存区]====>C[将操作提交至仓库]
预计很多人都有疑难,为什么这里写的是操作,而不是将文件增加至暂存区,因为 Git 治理的是批改而不是文件,咱们用一个例子来阐明这个问题。
首先,咱们在 Read.txt 中增加一段文字hello me
,而后将这次操作增加到暂存区,咱们查看此时的状态
it status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: Read.txt
可见此次批改曾经增加到了暂存区,而后咱们再对文件进行批改,减少一行hello you
,不将此次批改增加至暂存区。
git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: Read.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: Read.txt
咱们执行提交指令将批改提交至仓库,而后查看 git 状态
git status
On branch master
Your branch is ahead of 'origin/master' by 8 commits.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: Read.txt
咱们发现,未增加至暂存区的批改并未提交至仓库,咱们查看一下工作区和最新版本库的区别
~/CS61A$ git diff -- Read.txt
diff --git a/Read.txt b/Read.txt
index 1f8eec4..12ee40e 100644
--- a/Read.txt
+++ b/Read.txt
@@ -1,2 +1,3 @@
hello world
hello me
+hello you
如果 Git 治理的是文件自身,那么文件在提交时是什么样,提交的文件就是什么样,然而通过比照发现,版本库的文件和工作区的文件是不一样,咱们每次增加到暂存区的是对文件的操作步骤,比方创立删除文件,增加几行,删除几行,因为方才增加 hello you
这一行文字的批改操作并未增加至暂存区,提交时只提交暂存区有的操作,因而该操作未提交至仓库。
版本回退
下面 i 讲到,Git 治理的是批改,如果咱们在进行批改提交的过程中,不小心删除了最初一行hello me
,而咱们又须要这行文字该怎么办呢?
这时候就须要利用版本回退的性能了。
在 Git 中,咱们能够查看每次操作的记录
~/CS61A$ git log --pretty=oneline
aa03a474011bcb97e9f596d3b5c9a1b517726d05 (HEAD -> master) delete a line
05491fda20edff579daf14f24b7afed61d591842 add a line
a58d42838b1284034c4a9d52f0d2780ad251bda2 a
f67db85d1deeb3d7ca0020a332ac4e07bccf12b0 all
b96112ab41f972a9949e213347d7403dd2f8a03b 1
咱们要将版本回退到 delete a line
操作前,因而咱们应用 reset
指令
~/CS61A$ git reset --hard HEAD^
HEAD is now at 05491fd add a line
这里的 HEAD^ 示意上一个版本,如果上两个版本则为 ^^, 以此类推。
然而问题来了,如果咱们当初又想回到 delete a line
版本该怎么办呢?版本曾经回退了。
git 有一个命令记录了你的每次命令
~/CS61A$ git reflog
05491fd (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
aa03a47 HEAD@{1}: commit: delete a line
05491fd (HEAD -> master) HEAD@{2}: commit: add a line
于是咱们就能够利用 aa03a47
这个 id 来回到原来版本。
git reset --hard aa03a47
HEAD is now at aa03a47 delete a line
于是,版本又回来了。
批改撤销
有的时候咱们会因为手抖写错代码,比方咱们在 Read.txt(.sh)文件中增加一行‘rm -rf’,懂点 Linux 都晓得这是个致命操作。
如果你还没有将这次文件批改提交到暂存区,那么很简略,间接批改就好了,或者也能够应用指令
git checkout -- Read.txt
工作区的批改就被抛弃了,工作区文件的内容和版本库文件的内容雷同。
如果你曾经将文件批改增加到了暂存区,那么咱们须要应用另一个指令
git reset HEAD Read.txt
reset 指令不仅能够回退版本,当 HEAD 不 ^ 时,reset 指令也能够将暂存区的批改操作移除,而后再利用 checkout
指令同步版本库和工作区内容。
如果你曾经将批改提交到了版本库,那么依照版本回退的形式进行即可
git reset --hard HEAD^
如果你曾经将版本库内的内容推送到近程库,比方 Github,那就只能事在人为了,谁运行,谁遭殃。
近程库连贯
近程库增加 / 解除
首先,登陆 GitHub,而后,在右上角找到“Create a new repo”按钮,创立一个新的仓库
(图借的廖雪峰大 L 的):
在 Repository name 填入Read
,其余放弃默认设置,点击“Create repository”按钮,就胜利地创立了一个新的 Git 仓库:
而后,咱们在本地运行命令
git remote add origin git@github.com:xxxx/Read.git
xxx 处为你本人的 Github 账户名,就能够将本地的版本库和近程的库连接起来了。
将本地库所有内容推送至 Github 近程库的 master 分支。
git push(-u)origin master
加上了 -u
参数,Git 岂但会把本地的 master
分支内容推送的近程新的 master
分支,还会把本地的 master
分支和近程的 master
分支关联起来,在当前的推送或者拉取时就能够简化命令,不许须要退出 - u 参数。
SSH 正告
当你第一次应用 Git 的 clone
或者 push
命令连贯 GitHub 时,会失去一个正告:
The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?
这是因为 Git 应用 SSH 连贯,而 SSH 连贯在第一次验证 GitHub 服务器的 Key 时,须要你确认 GitHub 的 Key 的指纹信息是否真的来自 GitHub 的服务器,输出 yes
回车即可。
Git 会输入一个正告,通知你曾经把 GitHub 的 Key 增加到本机的一个信赖列表里了:
Warning: Permanently added 'github.com' (RSA) to the list of known hosts.
这个正告只会呈现一次,前面的操作就不会有任何正告了。
如果你切实放心有人假冒 GitHub 服务器,输出 yes
前能够对照 GitHub 的 RSA Key 的指纹信息是否与 SSH 连贯给出的统一。
解除近程库与本地库的关联关系
如果咱们须要解除本地库与近程库的关联关系,能够应用命令
git remote rm origin
近程库克隆
咱们有时须要把近程库从 Github 克隆下来,为了借鉴代码或是进行分布式工作,应用以下指令将近程库克隆至本地
git clone git@github.com:xxx/Read.git
分支治理
创立与合并分支
在版本回退里,你曾经晓得,每次提交,Git 都把它们串成一条工夫线,这条工夫线就是一个分支。截止到目前,只有一条工夫线,在 Git 里,这个分支叫主分支,即 master
分支。HEAD
严格来说不是指向提交,而是指向 master
,master
才是指向提交的,所以,HEAD
指向的就是以后分支。
当咱们创立新的分支,例如 dev
时,Git 新建了一个指针叫 dev
,指向master
雷同的提交,再把 HEAD
指向 dev
,就示意以后分支在dev
上
咱们建设一个新分支 dev
并切换至新分支
git checkout -b dev / git switch -c dev
如果切换至已有分支则
git checkout dev / git switch dev
如果只是创立分支
git branch dev
从当初开始,对工作区的批改和提交就是针对 dev
分支了,比方新提交一次后,dev
指针往前挪动一步,而 master
指针不变:
如果咱们在 dev
上的工作实现了,就能够把 dev
合并到 master
上。Git 怎么合并呢?最简略的办法,就是间接把 master
指向 dev
的以后提交,就实现了合并:
咱们切换至主分支,而后将 dev 分支合并至主分支 master
git checkout master
git merge dev
而后咱们能够保留分支,也能够删除分支,如果删除分支
git branch -d dev
多人合作
在理论开发中,咱们应该依照几个根本准则进行分支治理:
首先,master
分支应该是十分稳固的,也就是仅用来公布新版本,平时不能在下面干活;
那在哪干活呢?干活都在 dev
分支上,也就是说,dev
分支是不稳固的,到某个时候,比方 1.0 版本公布时,再把 dev
分支合并到 master
上,在 master
分支公布 1.0 版本;
你和你的小伙伴们每个人都在 dev
分支上干活,每个人都有本人的分支,时不时地往 dev
分支上合并就能够了。
所以,团队单干的分支看起来就像这样:
近程库克隆
团队单干的过程中首先要将近程库克隆至本地,具体形式见前文近程库克隆一节
实现克隆后,Git 主动把本地的 master 分支和近程的 master 分支对应起来了,默认近程仓库的名称为 origin
查看近程库的信息
~/CS61A$ git remote -v
origin git@github.com:x/CS61A.git (fetch)
origin git@github.com:x/CS61A.git (push)
下面显示了能够抓取和推送的 origin
的地址。如果没有推送权限,就看不到 push 的地址。
分支的推送
分支的推送有很多种模式,这里只介绍最简略的模式,假如,咱们曾经将近程库的 master 分支克隆到了本地,而后咱们创立了一个新的分支 dev,在新的分支进行工作,工作结束后咱们将 dev 分支合并至 master 分支,而后应用
git push origin master
就将该分支推送到了近程库
分支的抓取
在多人合作时可能会呈现一些问题,比方有一天,你的小伙伴曾经向 origin/master 分支推送了他的提交,而你碰巧也对同样的文件进行了批改,并试图推送,这时候你会发现,git 提醒推送失败,因为你的小伙伴的最新提交和你的提交有抵触。
因而咱们要在推送前先将 master 最新状况从近程抓下来,而后在本地进行合并和解决抵触。
解决抵触的办法如下
咱们晓得当咱们把近程的 master 分支抓取下来后,咱们本地的 dev 分支和近程 pull 下来的 master 分支存在抵触
这种状况下,Git 无奈执行“疾速合并”,只能试图把各自的批改合并起来,但这种合并会有抵触,咱们查看 一下 git 的状态
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: Read.txt
no changes added to commit (use "git add" and/or "git commit -a")
Git 通知咱们,Read.txt 文件存在抵触,咱们能够间接查看文件内容
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> dev
Git 用 <<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容,咱们批改如下后保留:
Creating a new branch is quick and simple.
Creating a new branch is quick and simple.
再提交批改给 master 分支
$ git add readme.txt
$ git commit -m "conflict fixed"
[master cf810e4] conflict fixed
Git 通知咱们抵触被解决了,于是咱们将 dev 分支合并至 master,而后执行 push
git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:x/Read.git
7a5e5dd..57c53ab master -> master
胜利。
标签治理
为什么须要标签?
Git 有 commit,为什么还要引入 tag?
“请把上周一的那个版本打包公布,commit 号是 6a5819e…”
“一串乌七八糟的数字不好找!”
如果换一个方法:
“请把上周一的那个版本打包公布,版本号是 v1.2”
“好的,依照 tag v1.2 查找 commit 就行!”
所以,tag 就是一个让人容易记住的有意义的名字,它跟某个 commit 绑在一起。
创立标签
在 Git 中打标签非常简单,首先,切换到须要打标签的分支上,而后敲击 tag 就能够打一个标签
git tag v1.0
利用 git tag
查看所有标签
$ git tag
v1.0
v2.0
v2.1
如果要对历史 commit 打标签,那就通过 git log 找到 commit 号
git tag v0.9 f287d34
查看每个标签的信息
$ git show v0.9
commit f52c63349bc3c1593499807e5c8e972b82c8f286 (tag: v0.9)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:56:54 2018 +0800
add merge
diff --git a/readme.txt b/readme.txt
...
而后依照版本回退一节的办法应用 reset
指令回退至对应版本打包即可。
留神,标签总是和某个 commit 挂钩。如果这个 commit 既呈现在 master 分支,又呈现在 dev 分支,那么在这两个分支上都能够看到这个标签。
操作标签
如果标签打错了,也能够删除:
$ git tag -d v0.1
Deleted tag 'v0.1' (was f15b0dd)
因为创立的标签都只存储在本地,不会主动推送到近程。所以,打错的标签能够在本地平安删除。如果要推送某个标签到近程,应用命令 git push origin <tagname>
,或应用git push origin --tags
推送所有标签。
如果要删除近程标签则先从本地删除标签,而后向近程同步删除指令
$ git push origin :refs/tags/v0.9
To github.com:x/Read.gi0t
- [deleted] v0.9
参考
1. 菜鸟教程 Git
2. 廖雪峰的 Git 教程
3.Git 官方网站