Git|分布式版本控制
主要的学习途径: Git教程by廖雪峰
Git Pro
掘金|多年Git使用心得&常见问题整理
可视化理解Git(基础)
可视化理解Git(进阶)
持续施工中……👷
安装与配置
查看Git的配置信息
返回
| credential.helper=osxkeychain
init.defaultbranch=main
user.name=tsai-shiyuan
user.email=Chase_Tsai@163.com
|
版本库
版本库又名仓库(Repository),可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪
如何跟踪?
⌘⇧. 查看隐藏文件夹,发现有 .git

创建版本库
Step 1. 首先创建一个文件夹并进入
Step 2. 通过 git init
命令把这个目录变成Git可以管理的仓库
返回
| Initialized empty Git repository in /Users/chasetsai/Desktop/Java/oopre_self/.git/
|
.git
目录是Git来跟踪管理版本库的,不要手动修改这个目录里面的文件
把文件添加到版本库
版本控制系统其实只能跟踪文本文件的改动
git commit
把文件提交到仓库(版本就会留在历史记录):
| git commit -m "wrote a readme file"
|
-m
后面输入的是本次提交的说明
返回:
| [main (root-commit) 2178f6d] wrote a readme file
1 file changed, 2 insertions(+) #readme.txt有两行内容
create mode 100644 readme.txt
|
版本控制
修改文件内容
修改 readme.txt
的内容
| Git is a distributed version control system.
Git is free software.
|
运行 git status
命令:
| $ git status
On branch main
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: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
|
git diff
查看修改(但尚未暂存)内容:
| $ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index d8036c1..013b5bc 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
\ No newline at end of file
|
git diff --cached
或 git diff --staged
查看已经暂存起来的变化
查看提交记录
再改一次并提交:
| Git is a distributed version control system.
Git is free software distributed under the GPL.
|
查看以上三次历史记录:
| $ git log
commit d1fc845fd70d0136e5776f3d841c2e5a57096378 (HEAD -> main)
Author: tsai-shiyuan <Chase_Tsai@163.com>
Date: Thu Sep 5 17:02:59 2024 +0800
append GPL
commit d830c503a915a9f6de1b9c93b6988a1637bda218
Author: tsai-shiyuan <Chase_Tsai@163.com>
Date: Thu Sep 5 17:00:44 2024 +0800
add distributed
commit 2178f6d545dfa36d9fcde4507b974dff72be0212
Author: tsai-shiyuan <Chase_Tsai@163.com>
Date: Thu Sep 5 16:51:15 2024 +0800
wrote a readme file
|
显示从最近到最远的提交日志
添加 --pretty=oneline
参数可以不显示作者和日期等信息
进而查看内容:
| $ git checkout [commit_id or branch_name]
|
看完后需要回到当前分支,再进行其他修改:
版本回退
用 HEAD
表示当前版本,也就是最新的提交 d1fc8...
,上一个版本就是 HEAD^
,上上一个版本就是 HEAD^^
,当然往上100个版本写100个 ^
比较容易数不过来,所以写成 HEAD~100
现在,我们要把当前版本 append GPL
回退到上一个版本 add distributed
,就可以使用 git reset
命令:
| $ git reset --hard HEAD^
HEAD is now at d830c50 add distributed
|
--hard
会回退到上个版本的已提交状态
--soft
会回退到上个版本的未提交状态
--mixed
会回退到上个版本已添加但未提交的状态
回退其实是改变指向:

此时 git log
:
| commit d830c503a915a9f6de1b9c93b6988a1637bda218 (HEAD -> main)
Author: tsai-shiyuan <Chase_Tsai@163.com>
Date: Thu Sep 5 17:00:44 2024 +0800
add distributed
commit 2178f6d545dfa36d9fcde4507b974dff72be0212
Author: tsai-shiyuan <Chase_Tsai@163.com>
Date: Thu Sep 5 16:51:15 2024 +0800
wrote a readme file
|
发现没有第三个版本了
版本穿梭
指定回到未来的某个版本:
| $ git reset --hard d1fc8 #未来的那个"地址",不用写全
HEAD is now at d1fc845 append GPL
|
可以用 git reflog
查看输过的命令,就能得到地址
工作区和暂存区
电脑里能看到的目录,比如 oopre_self
文件夹就是一个工作区 (Working Directory)
工作区有一个隐藏目录 .git
,这个不算工作区,而是Git的版本库 (Repository)

撤销修改
不小心加了一句但没 git add
:
| 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.
My stupid boss still prefers SVN.
|
用以下命令把在工作区的修改全部撤销:
| $ git checkout -- readme.txt
|
如果已经 git add
:
| $ git reset HEAD <file> # 但我的电脑显示 use "git restore --staged <file>" to unstage
|
可以把暂存区的修改撤销掉 (工作区不会变),HEAD
表示最新的版本
删除文件
删除也是一个修改操作,必须要从已跟踪文件清单中移除(移出暂存区)
假设 test.txt
已经通过了 git commit -m "add..."
,现使用命令 rm test.txt
删除了工作区的文件,工作区和版本库就不一致
- 从版本库中删除文件:
git rm test.txt
> git commit -m "remove test.txt"
很多时候,输入 git status
,git
会给出提示
从来没有被添加到版本库就被删除的文件,是无法恢复的!
停止跟踪文件 git rm --cached README.md
远程仓库
GitHub:提供Git仓库托管服务
本地Git仓库和GitHub仓库之间的传输是通过SSH加密
在用户主目录已找到 .ssh
目录,内含 id_rsa
和 id_rsa.pub
两个文件
id_rsa
是私钥,不能泄露出去,
id_rsa.pub
是公钥
SSH key的作用:GitHub需要识别出我们推送的提交确实是自己推送的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有我们自己才能推送
GitHub允许添加多个Key,把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送
添加远程库
Now: 已经在本地创建了一个Git仓库后 (进行了init),又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步
create a new repo

| $ git remote add origin git@github.com:tsai-shiyuan/oopre_self.git
|
从 origin
仓库的 main
分支下载文件
远程库的简称就是 origin
(默认)
| $ git push -u origin main
|
把本地库的内容推送到远程,教程上写的是 master
分支
-u
参数会把本地的 main
分支和远程的 main
分支关联起来,今后再使用就只需 git push origin main
把本地的最新修改推送至GitHub

删除远程库
先查看远程库信息:
| $ git remote -v
origin git@github.com:tsai-shiyuan/oopre_self.git (fetch)
origin git@github.com:tsai-shiyuan/oopre_self.git (push)
|
再根据名字删除,比如 origin
:
此处的"删除"是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。
从远程库克隆
登陆GitHub,创建一个 repo
用 git clone <...>
克隆一个本地库:
| $ git clone git@github.com:tsai-shiyuan/gitskills.git
|
oopre_self
里就多了 gitskills
文件夹,在url后添加名字参数,可以重命名本地的仓库
分支管理
创建与合并分支
每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支
HEAD
指向 master
,master
指向提交
一开始,master
分支是一条线,Git用 master
指向最新的提交,再用 HEAD
( HEAD
是当前的工作目录) 指向 master
,就能确定当前分支,以及当前分支的提交点

当我们创建新的分支,例如 dev
时,Git新建了一个指针叫 dev
,指向 master
相同的提交,再把 HEAD
指向 dev
,就表示当前分支在 dev
上

从现在开始,对工作区的修改和提交就是针对 dev
分支了,比如新提交一次后,dev
指针往前移动一步,而 master
指针不变

假如我们在 dev
上的工作完成了,就可以把 dev
合并到 master
上,方法:直接把 master
指向 dev
的当前提交

命令:
创建 dev
分支并切换到 dev
:
| $ git checkout -b dev
Switched to a new branch 'dev'
|
-b
参数表示创建并切换,相当于 git branch dev
> git checkout dev
查看当前分支:
| $ git branch
* dev
master
|
git branch -v
可以查看分支的最后一次提交
提交(推荐切换分支前先 commit):
| $ git add readme.txt
$ git commit -m "branch test"
[dev 7edc459] branch test
1 file changed, 2 insertions(+), 1 deletion(-)
|
切换回 master
分支:
切换回 master
分支后,再查看 readme.txt
文件,不会显示刚才添加的内容。因为那个提交是在 dev
分支上,而 master
分支此刻的提交点并没有变

现在,把 dev
分支的工作成果合并到 master
分支上:
| $ git merge dev
Updating 90c965a..7edc459
Fast-forward
readme.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
|
合并完成后,可以删除 dev
:
| $ git branch -d dev
Deleted branch dev (was 7edc459).
|
用途: 使用分支完成某个任务,合并后再删掉分支
switch切换分支 (更加科学) :
| $ git switch -c dev # 创建并切换到新的分支
Switched to a new branch 'dev'
$ git switch main # 切换回已有分支
|
解决冲突
移动到新的分支:
修改 readme.txt
的最后一行:
| Creating a new branch is quick AND simple.
|
在 feature1
上提交分支:
| $ git add readme.txt
$ git commit -m "AND simple"
[feature1 ea9b4dc] AND simple
1 file changed, 1 insertion(+), 1 deletion(-)
|
切换回 main
分支:
| $ git switch main
Switched to branch 'main'
|
修改 readme.txt
的最后一行:
| Creating a new branch is quick & simple.
|
在 main
上提交分支:
| $ git add readme.txt
$ git commit -m "& simple"
[main f0fd8a8] & simple
1 file changed, 1 insertion(+), 1 deletion(-)
|
现在,master
分支和 feature1
分支各自都分别有新的提交:

这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突:
| $ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
|
查看 readme.txt
:
| $ cat readme.txt
balabala
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1
|
我们删掉 & simple
有关句子,再保存并提交:
| $ git add readme.txt
$ git commit -m "conflict fixed"
[main 5bcb92b] conflict fixed
|

也可以用 git log
查看分支情况:
| $ git log --graph --pretty=oneline --abbrev-commit # --graph 参数用于看图
* 5bcb92b (HEAD -> main) conflict fixed
|\
| * ea9b4dc (feature1) AND simple
* | f0fd8a8 & simple
|/
* 7edc459 (dev) branch test
* 90c965a remove test.txt
* 047c9bb add test.txt
* edabc19 git tracks changes
* 69401a9 understand how stage works
* d1fc845 append GPL
* d830c50 add distributed
* 2178f6d wrote a readme file
|
删除 feature1
分支:
| $ git branch -d feature1
Deleted branch feature1 (was ea9b4dc).
|
分支管理策略
切换到 dev
分支,修改 readme.txt
并提交
切换回 main
准备合并 dev
分支,--no-ff
参数表示禁用 Fast forward
使用GitHub
GitHub作为免费的远程仓库
参与开源项目
bootstrap项目
点击 Fork
就在自己的账号下克隆了一个bootstrap仓库,然后,从自己的账号下clone,这样就能推送修改

- Bootstrap的官方仓库
twbs/bootstrap
- 在GitHub上克隆的仓库
my/bootstrap
- 自己克隆到本地电脑的仓库
想让bootstrap的官方库接受我的修改,就可以在GitHub上发起一个pull request
使用Gitee
国内的Git托管服务——Gitee