01、认识一下Git!—简介
Git是当时最先进、最干流的分布式版别控制体系,免费、开源!中心能力便是版别控制。再详细一点,便是面向代码文件的版别控制,代码的任何修正前史都会被记载办理起来,意味着能够康复到到曾经的恣意时刻状况。支撑跨区域多人协作修正,是团队项目开发的必备根底,所以Git也就成了程序员的必备技能。
首要特点:
- 开源免费,运用广泛。
- 强壮的文档(代码)的前史版别办理,直接记载完好快照(完好内容,而非差异),支撑回滚、比照。
- 分布式多人协作的的代码协同开发,几乎一切操作都是本地履行的,支撑代码兼并、代码同步。
- 简略易用的分支办理,支撑高效的创立分支、兼并分支。
Git是Linux之父被迫开发的,为了处理Linux紊乱的代码办理而开发的。Linux和Git之父 李纳斯托沃兹(Linus Benedic Torvalds),来自1969年的芬兰。
02、Git是干什么的?—根底概念
先了解下Git的根本概念,及根本结构、作业流程。
2.1、Git概念汇总
概念称号 | 描绘 |
---|---|
作业区(Workspace) | 便是在电脑里能看到的代码库目录,是咱们搬砖的当地,新增、修正的文件会提交到暂存区 |
暂存区(stage 或 index) | 用于临时寄存文件的修正,实践上上它仅仅一个文件(.git/index ),保存待提交的文件列表信息。 |
版别库/库房(Repository) | Git的办理库房,办理版别的数据库,记载文件/目录状况的当地,一切内容的修正记载(版别)都在这里。 |
服务端/长途库房(origin 或 remote) | 服务端的版别库,专用的Git服务器,为多人同享提供服务,承当中心服务器的角色。本地版别库经过push指令把代码推送到服务端版别库。 |
本地库房 | 用户机器上直接运用的的的版别库 |
分支(Branch) | 分支是从主线分离出去的“副本”,能够独立操作而互不搅扰,库房初始化就有一个默许主分支master 。 |
头(HEAD) | HEAD相似一个“指针”,指向当时活动 分支 的 最新版别。 |
提交(Commit) | 把暂存区的一切改变的内容提交到当时库房的活动分支。 |
推送(Push) | 将本地库房的版别推送到服务端(长途)库房,与别人同享。 |
拉取(Pull) | 从服务端(长途)库房获取更新到本地库房,获取别人同享的更新。 |
获取(Fetch) | 从服务端(长途)库房更新,作用同拉取(Pull),差异是不会主动兼并。 |
抵触(Conflict) | 多人对同一文件的作业副本进行更改,并将这些更改兼并到库房时就会面临抵触,需求人工兼并处理。 |
兼并(Merge) | 对有抵触的文件进行兼并操作,Git会主动兼并改变内容,无法主动处理的抵触内容会提示人工处理。 |
标签(Tags) | 标签指的是某个分支某个特守时刻点的状况,能够了解为提交记载的别号,常用来标记版别。 |
master(或main) | 库房的“master ”分支,默许的主分支,初始化库房就有了。Github上创立的库房默许姓名为“main ” |
origin/master | 表明长途库房(origin )的“master ”分支 |
origin/HEAD | 表明长途库房(origin )的最新提交的方位,一般状况等于“origin/master ” |
2.2、作业区/暂存区/库房
作业区、暂存区、版别库是Git最根本的概念,联系如下图:
作业区(Workspace)便是在电脑里能看到的代码库目录,是咱们搬砖的当地,新增、修正的文件会提交到暂存区。
- 在这里新增文件、修正文件内容,或删去文件。
暂存区(stage或index) 用于临时寄存文件的修正,实践上上它仅仅一个文件(.git/index),保存待提交的文件列表信息。
- 用
git add
指令将作业区的修正保存到暂存区。
版别库/库房(Repository /rpztri/ 库房)Git的办理库房,办理版别的数据库,记载文件/目录状况的当地,一切内容的修正记载(版别)都在这里。便是作业区目录下的躲藏文件夹.git
,包含暂存区、分支、前史记载等信息。
- 用
git commit
指令将暂存区的内容正式提交到版别库。 -
master
为库房的默许分支master
,HEAD是一个“指针”指向当时分支的最新提交,默许指向最新的master
。
如上图,为对应本地库房目录的结构联系。
-
KWebNote
为项目目录,也便是Git作业区。 - 项目根目录下躲藏的
.git
目录便是Git库房目录了,寄存了一切Git办理的信息。 -
.git/config
为该库房的装备文件,可经过指令修正或直接修正。 -
index
文件便是寄存的暂存区内容。
2.3、Git根本流程(图)
Git的作业流程中心就下面几个步骤,把握了就能够开端写Bug了。
- 0、预备库房:创立或从服务端克隆一个库房。
- 1、搬砖:在作业目录中增加、修正代码。
- 2、暂存(git add):将需求进行版别办理的文件放入暂存区域。
- 3、提交(git commit):将暂存区域的文件提交到Git库房。
- 4、推送(git push):将本地库房推送到长途库房,同步版别库。
- 5、获取更新(fetch/pull):从服务端更新到本地,获取别人推送的更新,与别人协作、同享。
-
git commit -a
指令省掉了add
到暂存区的步骤,直接提交作业区的修正内容到版别库,不包含新增的文件。 -
git fetch
、git pull
都是从长途服务端获取最新记载,差异是git pull
多了一个步骤,便是主动兼并更新作业区。 -
git checkout .
、git checkout [file]
会铲除作业区中未增加到暂存区的修正,用暂存区内容替换作业区。 -
git checkout HEAD .
、git checkout HEAD [file]
会铲除作业区、暂存区的修正,用HEAD指向的当时分支最新版别替换暂存区、作业区。 -
git diff
用来比照不同部分之间的差异,如暂存区、作业区,最新版别与未提交内容,不同版别之间等。 -
git reset
是专门用来吊销修正、回退版别的指令,代替上面checkout
的吊销功用。
2.4、Git状况(图)
Git在履行提交的时分,不是直接将作业区的修正保存到库房,而是将暂存区域的修正保存到库房。要提交文件,首要需求把文件加入到暂存区域中。因而,Git办理的文件有三(+2)种状况:
- 未盯梢(untracked):新增加的文件,或被移除盯梢的文件,未树立盯梢,经过
git add
增加暂存并树立盯梢。 - 未修正:从库房签出的文件默许状况,修正后便是“已修正”状况了。
- 已修正(modified):文件被修正后的状况。
- 已暂存(staged):修正、新增的文件增加到暂存区后的状况。
- 已提交(committed):从暂存区提交到版别库。
03、起步:Git装置装备
Git官网:www.git-scm.com/ 下载装置包进行装置。Git的运用有两种办法:
-
指令行:Git的指令经过体系指令行东西,或Git提供的指令行东西运转(
C:\Program Files\Git\git-bash.exe
) - GUI东西:Windows(GUI)、Mac(GUI)东西,需独自装置,运用更简略、更易上手。
指令git --version
检查装置版别号
$ git --version
git version 2.33.0.windows.2
本文是在Windows 渠道上完结的,不过这个对学习Git没什么影响。
3.1、Git的装备文件
Git有三个首要的装备文件:三个装备文件的优先级是① < ② < ③
-
① 体系大局装备(–system):包含了适用于体系一切用户和一切库房(项目)的装备信息,寄存在Git装置目录下
C:\Program Files\Git\etc\gitconfig
。 -
② 用户大局装备(–system):当时体系用户的大局装备,寄存用户目录:
C:\Users\[体系用户名]\.gitconfig
。 -
③ 库房/项目装备(–local):库房(项目)的特定装备,寄存在项目目录下
.git/config
#检查git装备
git config --list
git config -l
#检查体系装备
git config --system --list
#检查当时用户(global)大局装备
git config --list --global
#检查当时库房装备信息
git config --local --list
库房的装备是上面多个装备的调集:
$ git config --list
$ git config -l
diff.astextplain.textconv=astextplain
http.sslbackend=openssl
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
core.autocrlf=true
core.fscache=true
core.symlinks=false
pull.rebase=false
credential.helper=manager-core
credential.https://dev.azure.com.usehttppath=true
init.defaultbranch=master
user.name=Kanding
user.email=123anding@163.com
3.2、装备-初始化用户
当装置Git后首要要做的作业是装备你的用户信息—— 告诉Git你是谁?装备 用户名、邮箱地址,每次提交文件时都会带上这个用户信息,检查前史记载时就知道是谁干的了。
装备用户信息:
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
# 装备完后,看看用户装备文件:
$ cat 'C:\Users\Kwongad\.gitconfig'
[user]
name = Kanding
email = 123anding@163.com
-
user.name
为用户名,user.email
为邮箱。 -
--global
:config
的参数,表明用户大局装备。假如要给特定库房装备用户信息,则用参数--local
装备即可,或直接在库房装备文件.git/config
里修正。
3.3、装备-疏忽.gitignore
作业目录中的文件并不是全都需求归入版别办理,如日志、临时文件、私有装备文件等不需求也不能归入版别办理,那该怎样办呢?
在作业区根目录下创立“.gitignore
”文件,文件中装备不需求进行版别办理的文件、文件夹。“.gitignore
”文件本身是被归入版别办理的,能够同享。有如下规矩:
-
#
符号最初为注释。 - 能够运用Linux通配符。
- 星号(*)代表恣意多个字符,
- 问号(?)代表一个字符,
- 方括号([abc])代表可选字符范围,
- 大括号({string1,string2,…})代表可选的字符串等。
- 感叹号(
!
)最初:表明破例规矩,将不被疏忽。 - 途径分隔符(/f)最初:,表明要疏忽根目录下的文件
f
。 - 途径分隔符(f/)结束:,表明要疏忽文件夹
f
下面的一切文件。
#为注释
*.txt #疏忽一切“.txt”结束的文件
!lib.txt #lib.txt在外
/temp #仅疏忽项目根目录下的temp文件,不包含其它目录下的temp,如不包含“src/temp”
build/ #疏忽build/目录下的一切文件
doc/*.txt #会疏忽 doc/notes.txt 但不包含 doc/server/arch.txt
各种言语项目的常用
.gitignore
文件装备:github.com/github/giti…
04、Git的GUI东西们
假如不想用指令行东西,完全能够装置一个Git的GUI东西,用的更简略、更舒服。不必记那么多指令了,极易上手,不过Git根底仍是需求学习了解一下的。
❓对于Git,建议用指令行,这样你才干真的了解Git的思想? ✔️其实都仅仅东西罢了,适合自己的便是最好的,没必要纠结,多写点Bug更重要!
-
TortoiseGit:小乌龟,SVN时代就很盛行的代码办理GUI利器。
- 只有Windows版别,支撑中文,需求独自下载装置中文言语包。
- ✔️开源,免费,与文件办理器的良好集成。
- ✔️内置抵触比照处理东西。
-
Sourcetree:SourceTree是老牌的Git GUI办理东西了,也号称是最好用的Git GUI东西。
- ✔️适用于 Windows 和 Mac 体系,内置中文版,主动识别言语。
- ✔️免费、功用强壮,运用简略。
- ✔️功用丰厚,根本操作和高档操作都规划得非常流畅,适合初学者上手,支撑Git Flow。
- 无抵触比照东西,支撑装备第三方组件。
- GitHub Desktop:Github官方出品的Git办理东西。
- GitKraken:GitKraken是一个跨渠道GUI Git客户端,有免费版,专业版和企业版,这些版别启用了不同的功用。
4.1、SourceTree
SourceTree的官网 下载装置包,支撑Window、Mac体系,依照提示完结装置。
- SourceTree支撑办理多个库房,经过+按钮,可选择多种办法增加库房。
- 然后便是可视化的库房办理了,不必记住繁琐的指令(参数)了,可视化操作。
4.2、TortoiseGit
TortoiseGit 官网下载装置包,及中文言语包,依照提示完结装置。小乌龟的Git是集成到操作体系里的,直接右键文件夹就能够进行Git操作了。
- 先进入设置:右键文件夹菜单 –> TortoiseGit –> Settings 进入设置,设置中文言语。
- 小乌龟的各种Git操作都在右键菜单了,深度集成到了操作体系的资源办理器中了,文件图标也是有Git状况的,比较简单分辨。
4.3、VSCode中的Git
VSCode自带的Git东西根本已经能够满足日常运用了,既有可视化功用,也能敲指令,习惯了不就不必装置其他GUI东西了。不过仍是能够再装置一些VSCode插件,来增强Git功用。
- GitLens :在团队项目开发中非常有用,必备!!!用于快速检查代码提交前史记载,在代码上会显现最近的修正信息,包含提交者,只就这一点就值得推荐了。
- Git History:能够轻松快速阅读Git文件操作前史记载的东西,可视化展示,操作简略。
05、Git运用入门
5.1、创立库房
创立本地库房的办法有两种:
- 一种是创立全新的库房:
git init
,会在当时目录初始化创立库房。 - 另一种是克隆长途库房:
git clone [url]
# 预备一个文件夹“KwebNote”作为库房目录,指令行进入该文件夹
Kwongad@Kwongad-T14 MINGW64 ~
$ cd d:
Kwongad@Kwongad-T14 MINGW64 /d
$ cd Project_Files
Kwongad@Kwongad-T14 MINGW64 /d/Project_Files
# 屡次cd指令进入到库房目录KwebNote:“cd <目录称号>”指令进入目录,“cd ..”回来上级目录(有空格)
Kwongad@Kwongad-T14 MINGW64 /d/Project_Files/github.kwong/KwebNote
# 开端初始化项目,也可指定目录:git init [文件目录]
$ git init
Initialized empty Git repository in D:/Project_Files/github.Kwong/KwebNote/.git/
注意:Git指令的履行,都需在库房目录下。
创立完多出了一个被躲藏的.git
目录,这便是本地库房Git的作业场所。
克隆长途库房,如在github上创立的库房“https://github.com/kwonganding/KWebNote.git
”
$ git clone 'https://github.com/kwonganding/KWebNote.git'
Cloning into 'KWebNote'...
remote: Enumerating objects: 108, done.
remote: Counting objects: 100% (108/108), done.
remote: Compressing objects: 100% (60/60), done.
remote: Total 108 (delta 48), reused 88 (delta 34), pack-reused 0
Receiving objects: 100% (108/108), 9.36 KiB | 736.00 KiB/s, done.
Resolving deltas: 100% (48/48), done.
会在当时目录下创立“KWebNote”项目目录。
5.2、暂存区add
能够简略了解为,git add
指令便是把要提交的一切修正放到暂存区(Stage),然后,履行git commit
就能够一次性把暂存区的一切修正提交到库房。
指令 | 描绘 |
---|---|
git add [file1] [file2] | 增加文件到暂存区,包含修正的文件、新增的文件 |
git add [dir] | 同上,增加目录到暂存区,包含子目录 |
git add . | 同上,增加一切修正、新增文件(未盯梢)到暂存区 |
git rm [file] | 删去作业区文件,而且将这次删去放入暂存区 |
# 增加指定文件到暂存区,包含被修正的文件
$ git add [file1] [file2] ...
# 增加当时目录的一切文件到暂存区
$ git add .
# 删去作业区文件,而且将这次删去放入暂存区
$ git rm [file1] [file2] ...
# 改名文件,而且将这个改名放入暂存区
$ git mv [file-original] [file-renamed]
修正文件“R.md”,未暂存:
履行git add .
暂存:
5.3、提交commit-记载
git commit
提交是以时刻顺序排列被保存到数据库中的,就如游戏关卡相同,每一次提交(commit)就会发生一条记载:id + 描绘 + 快照内容
。
-
commit id:依据修正的文件内容选用摘要算法(SHA1)核算出不重复的40位字符,这么长是因为Git是分布式的,要确保唯一性、完好性,一般本地指令中能够只用前几位(6)。即便多年以后,依然可经过
id
找到曾经的任何内容和变动,再也不必担心丢失了。 - 描绘:针对本次提交的描绘阐明,建议精确填写,就跟代码中的注释相同,很重要。
-
快照:便是完好的版别文件,以对象树的结构存在库房下
\.git\objects
目录里,这也是Git效率高的诀窍之一。
- SHA1 是一种哈希算法,能够用来生成数据摘要
- Git不适合大的非文本文件,会影响核算摘要、快照的功用。
多个提交就构成了一条时刻线,每次提交完,会移动当时分支master
、HEAD
的“指针”方位。
Sourcetree上的前史记载:
一般状况,每完结一个小功用、一个Bu就能够提交一次,这样会构成比较明晰的前史记载。
指令:
指令 | 描绘 |
---|---|
git commit -m ‘阐明’ | 提交改变,参数-m 设置提交的描绘信息,应该正确提交,不带该参数会进入阐明修正形式 |
git commit -a | 参数-a ,表明直接从作业区提交到版别库,略过了git add 步骤,不包含新增的文件 |
git commit [file] | 提交暂存区的指定文件到库房区 |
git commit –amend -m | 运用一次新的commit ,代替上一次提交,会修正commit 的hash 值(id) |
git log -n20 | 检查日志(最近20条),不带参数-n 则显现一切日志 |
git log -n20 –oneline | 参数“--oneline ”能够让日志输出更简练(一行) |
git log -n20 –graph | 参数“--graph ”可视化显现分支联系 |
git log –follow [file] | 显现某个文件的版别前史 |
git blame [file] | 以列表形式显现指定文件的修正记载 |
git reflog | 检查一切可用的前史版别记载(实践是HEAD改变记载),包含被回退的记载(重要) |
git status | 检查本地库房状况,比较常用的指令,加参数-s 简练形式 |
经过git log
指令能够检查提交记载日志,能够很便利的检查每次提交修正了哪些文件,改了哪些内容,然后进行康复等操作。
# 提交暂存区到库房区
$ git commit -m [message]
# 提交一切修正到库房
$ git commit -a -m'修正README的版权信息'
# 提交暂存区的指定文件到库房区
$ git commit [file1] [file2] ... -m [message]
# 运用一次新的commit,代替上一次提交
# 假如代码没有任何新改变,则用来改写上一次commit的提交信息
$ git commit --amend -m [message]
$ git log -n2
commit 412b56448568ff362ef312507e78797befcf2846 (HEAD -> main)
Author: Kanding <123anding@163.com>
Date: Thu Dec 1 19:02:22 2022 +0800
commit c0ef58e3738f7d54545d8c13d603cddeee328fcb
Author: Kanding <123anding@163.com>
Date: Thu Dec 1 16:52:56 2022 +0800
# 用参数“--oneline”能够让日志输出更简练(一行)
$ git log -n2 --oneline
5444126 (HEAD -> main, origin/main, origin/HEAD) Update README.md
228362e Merge branch 'main' of github.com:kwonganding/KWebNote
5.4、Git的“指针”引证们
Git中最重要的便是提交记载了,其他如标签、分支、HEAD 都对提交记载的“指针”引证,指向这些提交记载,了解这一点很重要。
- 提交记载之间也存在“指针”引证,每个提交会指向其上一个提交。
-
标签 便是对某一个提交记载的的 固定 “指针”引证,取一个别号更简单回忆一些要害节点。存储在作业区根目录下
.git\refs\tags
。 -
分支 也是指向某一个提交记载的“指针”引证,“指针”方位可变,如提交、更新、回滚。存储在作业区根目录下
.git\refs\heads
。 -
HEAD:指向当时活动分支(最新提交)的一个“指针”引证,存在在“
.git/HEAD
”文件中,存储的内容为“ref: refs/heads/master
”。
上图中:
-
HEAD
一直指向当时活动分支,多个分支只能有一个处于活动状况。 - 标签
t1
在某一个提交上创立后,就不会变了。而分支、HEAD
的方位会改变。
翻开这些文件内容看看,就更简单了解这些“指针”的真面目了。
# tag
$ git tag -a 'v1' -m'v1版别'
$ cat .git/refs/tags/v1
a2e2c9caea35e176cf61e96ad9d5a929cfb82461
# main分支指向最新的提交
$ cat .git/refs/heads/main
8f4244550c2b6c23a543b741c362b13768442090
# HEAD指向当时活动分支
$ cat .git/HEAD
ref: refs/heads/main
# 切换到dev分支,HEAD指向了dev
$ git switch dev
Switched to branch 'dev'
$ cat .git/HEAD
ref: refs/heads/dev
这里的主分支姓名为“main
”,是因为该库房是从Github上克隆的,Github上创立的库房默许主分支姓名便是“main
”,本地创立的库房默许主分支姓名为“master
”。
“指针”引证:之所以用引号的“指针”,是为了便于统一和了解。和指针原理相似,都是一个指向,仅仅实践上或许更复杂一点,且不同的“指针”引证会有差异。
5.5、提交的唯一标识id,HEAD~n是什么意思?
每一个提交都有一个唯一标识,首要便是提交的hash
值commit id
,在许多指令中会用到,如版别回退、拣选提交等,需求指定一个提交。那标识唯一提交有两种办法:
- 首要便是
commit id
,一个40位编码,指令中运用的时分能够只输入前几位(6位)即可。 - 还有一种便是
HEAD~n
,是依据当时HEAD
方位的一个相对坐标。-
HEAD
表明当时分支的最新版别,是比较常用的参数。 -
HEAD^
上一个版别,HEAD^^
上上一个版别。 -
HEAD~
或HEAD~1
表明上一个版别,以此类推,HEAD^10
为最近第10个版别。 -
HEAD@{2}
在git reflog
日志中标记的提交记载索引。
-
经过git log
、git reflog
能够检查前史日志,能够看每次提交的唯一编号(hash)。差异是git reflog
能够检查一切操作的记载(实践是HEAD改变记载),包含被吊销回退的提交记载。
$ git reflog -n10
5acc914 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~
738748b (dev) HEAD@{1}: reset: moving to HEAD~
9312c3e HEAD@{2}: reset: moving to HEAD~
db03fcb HEAD@{3}: reset: moving to HEAD~
1b81fb3 HEAD@{4}: reset: moving to HEAD~
41ea423 HEAD@{5}: reset: moving to HEAD~
d3e15f9 HEAD@{6}: reset: moving to d3e15f9
1b81fb3 HEAD@{7}: reset: moving to HEAD~1
41ea423 HEAD@{8}: reset: moving to HEAD~
d3e15f9 HEAD@{9}: reset: moving to HEAD~
5.6、比较diff
git diff
用来比较不同文件版别之间的差异。
指令 | 描绘 |
---|---|
git diff | 检查暂存区和作业区的差异 |
git diff [file] | 同上,指定文件 |
git diff –cached | 检查已暂存的改动,便是暂存区与新版别HEAD 进行比较 |
git diff –staged | 同上 |
git diff –cached [file] | 同上,指定文件 |
git diff HEAD | 检查已暂存的+未暂存的一切改动,便是与最新版别HEAD 进行比较 |
git diff HEAD~ | 同上,与上一个版别比较。HEAD~ 表明上一个版别,HEAD~10 为最近第10个版别 |
git diff [id] [id] | 检查两次提交之间的差异 |
git diff [branch] | 检查作业区和分支直接的差异 |
☘️画个图更明晰些:
# 检查文件的修正
$ git diff README.md
# 检查两次提交的差异
$ git diff 8f4244 1da22
# 显现今日你写了多少行代码:作业区+暂存区
$ git diff --shortstat "@{0 day ago}"
06、长途库房
Git作为分布式的版别办理体系,每个终端都有自己的Git库房。但团队协作还需一个中间库房,作为中心,同步各个库房。所以服务端(长途)库房就来承当这个职责,服务端不只有库房,还配套相关办理功用。
能够用公共的Git服务器,也能够自己建立一套Git服务器。
- 公共Git服务器,如Github、Gitlab、码云Gitee、腾讯Coding等。
- 建立私有Git服务器,如开源的Gitlab、Gitea、等。
6.1、长途用户登录
Git服务器一般提供两种登录验证办法:
-
HTTS:依据HTTPS衔接,运用用户名、暗码身份验证。
- 每次都要输入用户名、暗码,当然能够记住。
- 地址形式:
https://github.com/kwonganding/KWebNote.git
-
SSL:选用SSL通信协议,依据公私钥进行身份验证,所以需求额定装备公私秘钥。
- 不必每次输入用户名、暗码,比较推荐的办法。
- 地址形式:
git@github.com:kwonganding/KWebNote.git
#检查当时长途库房运用的那种协议衔接:
$ git remote -v
origin git@github.com:kwonganding/KWebNote.git (fetch)
origin https://github.com/kwonganding/KWebNote.git (push)
# 更改为https地址,即可切换衔接形式。还需求禁用掉SSL, 才干正常运用https办理git
git config --global http.sslVerify false
长途用户登录:HTTS
依据HTTPS的地址衔接长途库房,Github的共有库房克隆、拉取(pull)是不需求验证的。
$ git clone 'https://github.com/kwonganding/KWebNote.git'
Cloning into 'KWebNote'...
# 库房装备文件“.git/config”
[remote "origin"]
url = https://github.com/kwonganding/KWebNote.git
fetch = +refs/heads/*:refs/remotes/origin/*
pushurl = https://github.com/kwonganding/KWebNote.git
推送(push)代码的时分就会提示输入用户名、暗码了,不然无法提交。记住用户暗码的办法有两种:
-
URL地址装备:在原本URL地址上加上用户名、暗码,
https://
后加用户名:暗码@
# 直接修正库房的装备文件“.git/config”
[remote "origin"]
url = https://用户名:暗码@github.com/kwonganding/KWebNote.git
fetch = +refs/heads/*:refs/remotes/origin/*
pushurl = https://github.com/kwonganding/KWebNote.git
-
本地缓存:会创立一个缓存文件
.git-credentials
,存储输入的用户名、暗码。
# 参数“--global”大局有用,也能够针对库房设置“--local”
# store 表明永久存储,也能够设置临时存储
git config --global credential.helper store
# 存储内容如下,翻开文件“库房\.git\.git-credentials”
https://kwonganding:[加密内容付费可见]@github.com
长途用户登录:SSH
SSH(Secure Shell,安全外壳)是一种网络安全协议,经过加密和认证机制完结安全的拜访和文件传输等业务,多用来进行长途登录、数据传输。SSH经过公钥、私钥非对称加密数据,所以SSH需求生成一个公私钥对,公钥放服务器上,私有自己留着进行认证。
① 生成公私钥:经过Git指令ssh-keygen -t rsa
生成公私钥,一路回车即可完结。生成在“C:\Users\用户名\.ssh
”目录下,文件id_rsa.pub
的内容便是公钥。
② 装备公钥:翻开id_rsa.pub
文件,复制内容。Github上,翻开Setting
➤ SSH and GPG keys
➤ SSH keys
➤ 按钮New SSH key
,标题(Title)随意,秘钥内容粘贴进去即可。
SSH装备完后,可用ssh -T git@github.com
来检测是否衔接成功。
$ ssh -T git@github.com
Hi kwonganding! You've successfully authenticated, but GitHub does not provide shell access.
6.2、长途库房指令
指令 | 描绘 |
---|---|
git clone [git地址] | 从长途库房克隆到本地(当时目录) |
git remote -v | 检查一切长途库房,不带参数-v 只显现称号 |
git remote show [remote] | 显现某个长途库房的信息 |
git remote add [name] [url] | 增加一个新的长途库房,并命名 |
git remote rename [old] [new] | 修正长途库房称号 |
git pull [remote] [branch] | 取回长途库房的改变,并与本地版别兼并 |
git pull | 同上,针对当时分支 |
git fetch [remote] | 获取长途库房的一切变动到本地库房,不会主动兼并!需求手动兼并 |
git push | 推送当时分支到长途库房 |
git push [remote] [branch] | 推送本地当时分支到长途库房的指定分支 |
git push [remote] –force/-f | 强行推送当时分支到长途库房,即便有抵触,⚠️很风险! |
git push [remote] –all | 推送一切分支到长途库房 |
git push –u | 参数–u 表明与长途分支树立相关,第一次履行的时分用,后面就不需求了 |
git remote rm [remote-name] | 删去长途库房 |
git pull –rebase | 运用rebase的形式进行兼并 |
6.3、推送push/拉取pull
git push
、git pull
是团队协作中最常用的指令,用于同步本地、服务端的更新,与别人协作。
推送(push):推送本地库房到长途库房。
- 假如推送的更新与服务端存在抵触,则会被回绝,
push
失败。一般是有其别人推送了代码,导致文件抵触,能够先pull
代码,在本地进行兼并,然后再push
。
拉取(pull):从服务端(长途)库房更新到本地库房。
-
git pull
:拉取服务端的最新提交到本地,并与本地兼并,兼并进程同分支的兼并。 -
git fetch
:拉取服务端的最新提交到本地,不会主动兼并,也不会更新作业区。
6.4、fetch与pull有什么不同?
两者都是从服务端获取更新,首要差异是fetch
不会主动兼并,不会影响当时作业区内容。
git pull
=git fetch
+git merge
- 如下面图中,
git fetch
只获取了更新,并未影响master
、HEAD
的方位。 - 要更新
master
、HEAD
的方位需求手动履行git merge
兼并。
# fetch只更新版别库
$ git fetch
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 663 bytes | 44.00 KiB/s, done.
From github.com:kwonganding/KWebNote
2ba12ca..c64f5b5 main -> origin/main
# 履行兼并,兼并自己
$ git merge
Updating 2ba12ca..c64f5b5
Fast-forward
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
07、Git利器-分支
分支是从主线分离出去的“副本”,分支就像是平行宇宙,可独立开展,独立修正、提交,也能够和其他分支兼并。分支是Git的中心必杀利器之一,分支创立、切换、删去都非常快,他非常的轻量。所以,早建分支!多用分支!
7.1、分支Branch
比如有一个项目团队,预备10月份发布新版别,要新开发一堆黑科技功用,占领市场。你和小伙伴“小美”一同负责开发一个新功用A,开发周期2周,在这两周你们的代码不能影响其别人,不影响主分支。这个时分就能够为这个新功用创立一个分支,你们两在这个分支上干活,2周后代码开发完了、测试经过,就能够兼并进要发版的开发分支了。安全、高效,不影响其别人作业,完美!
在实践项目中,一般会建几个主线分支。
- master:作为主分支,寄存安稳的代码,便是开发后测试经过的代码,不允许随意修正和兼并。
- 开发分支:用于团队日常开发用,比如团队计划10月份开发10个功用并发版,则在此分支上进行,不影响主分支的安稳。
- 功用A分支:开发人员依据自己的需求,能够创立一些临时分支用于特定功用的开发,开发完毕后再兼并到开发分支,并删去该分支。
分支便是指向某一个提交记载的“指针”引证,因而创立分支是非常快的,不管库房多大。当咱们运转git branch dev
创立了一个姓名为dev
的分支,Git实践上是在.git\refs\heads
下创立一个dev
的引证文件(没有扩展名)。
$ git branch dev
$ cat .git/refs/heads/dev
ca88989e7c286fb4ba56785c2cd8727ea1a07b97
7.2、分支指令
指令 | 描绘 |
---|---|
git branch | 列出一切本地分支,加参数-v 显现详细列表,下同 |
git branch -r | 列出一切长途分支 |
git branch -a | 列出一切本地分支和长途分支,用不同颜色区分 |
git branch [branch-name] | 新建一个分支,但依然停留在当时分支 |
git branch -d dev | 删去dev 分支,-D(大写)强制删去 |
git checkout -b dev | 从当时分支创立并切换到dev 分支 |
git checkout -b feature1 dev | 从本地dev 分支代码创立一个 feature1 分支,并切换到新分支 |
git branch [branch] [commit] | 新建一个分支,指向指定commit id
|
git branch –track [branch] [remote-branch] | 新建一个分支,与指定的长途分支树立相关 |
git checkout -b hotfix remote hotfix | 从远端remote 的hotfix 分支创立本地hotfix 分支 |
git branch –set-upstream [branch] [remote-branch] | 在现有分支与指定的长途分支之间树立盯梢相关:git branch --set-upstream hotfix remote/hotfix
|
git checkout [branch-name] | 切换到指定分支,并更新作业区 |
git checkout . | 吊销作业区的(未暂存)修正,把暂存区康复到作业区。 |
git checkout HEAD . | 吊销作业区、暂存区的修正,用HEAD 指向的当时分支最新版别替换 |
git merge [branch] | 兼并指定分支到当时分支 |
git merge –no-ff dev | 兼并dev 分支到当时分支,参数--no-ff 禁用快速兼并形式 |
git push origin –delete [branch-name] | 删去长途分支 |
git rebase master | 将当时分支变基兼并到master 分支 |
✅switch:新的分支切换指令 | 切换功用和checkout 相同,switch 只单纯的用于切换 |
git switch master | 切换到已有的master 分支 |
git switch -c dev | 创立并切换到新的dev 分支 |
关于
checkout
指令:checkout
是Git的底层指令,比较常用,也比较风险,他会重写作业区。支撑的功用比较多,能吊销修正,能切换分支,这也导致了这个指令比较复杂。在Git 2.23版别以后,增加了git switch
、git reset
指令。
git switch
:专门用来完结分支切换。git reset
:专门用来完结本地修正的吊销,更多可参考后续“reset”内容。
$ git branch
dev
* main
# 列出了当时的一切分支,星号“*”最初的“main”为当时活动分支。
7.3、分支的切换checkout
代码库房能够有多个分支,master
为默许的主分支,但只有一个分支在作业状况。所以要操作不同分支,需求切换到该分支,HEAD
便是指向当时正在活动的分支。
# 切换到dev分支,HEAD指向了dev
# 此处 switch 作用同 checkout,switch只用于切换,不像checkout功用许多
$ git switch dev
Switched to branch 'dev'
$ cat .git/HEAD
ref: refs/heads/dev
运用 git checkout dev
切换分支时,干了两件事:
- ①、
HEAD
指向dev
:修正HEAD
的“指针”引证,指向dev
分支。 - ②、还原作业空间:把
dev
分支内容还原到作业空间。
此刻的活动分支便是dev
了,后续的提交就会更新到dev
分支了。
❓切换时还没提交的代码怎样办?
- 假如修正(包含未暂存、已暂存)和待切换的分支没有抵触,则切换效果,且未提交修正会一同带过去,所以要注意!
- 假如有抵触,则会报错,提示先提交或躲藏,关于躲藏可检查后续章节内容“stash”。
7.4、兼并merge&抵触
把两个分支的修正内容兼并到一同,常用的兼并指令git merge [branch]
,将分支[branch]
兼并到当时分支。依据要兼并的内容的不同,详细兼并进程就会有多种状况。
快速兼并(Fast forward)
如下图,master
分支么有任何提交,“git merge dev
”兼并分支dev
到master
,此刻兼并速度就非常快,直接移动master
的“指针”引证到dev
即可。这便是快速兼并(Fast forward),不会发生新的提交。
- 兼并
dev
到master
,注意要先切换到master
分支,然后履行git merge dev
,把dev
兼并到当时分支。
强制不必快速兼并:
git merge --no-ff -m "merge with no-ff" dev
,参数--no-ff
不启用快速兼并,会发生一个新的兼并提交记载。
普通兼并
假如master
有改变,存在分支穿插,则会把两头的改变兼并成一个提交。
- 假如两头改变的文件不同,没有什么抵触,就主动兼并了。
- 假如有修正同一个文件,则会存在抵触,究竟该选用哪边的,程序无法判断,就换发生抵触。抵触内容需求人工修正后再从头提交,才干完结最终的兼并。
上图中,创立dev
分支后,两个分支都有修正提交,因而两个分支就不在一条顺序线上了,此刻兼并dev
到master
就得把他们的修正进行兼并操作了。
-
v5
、v7
一同先人是v4
,从这里开端分叉。 - Git 会用两个分支的末端
v6
和v8
以及它们的一同先人v4
进行三方兼并核算。兼并之后会生成一个新(和并)提交v9
。 - 兼并提交
v9
就有两个先人v6
、v8
。
处理抵触<<<<<<< HEAD
在有抵触的文件中,<<<<<<< HEAD
最初的内容就表明是有抵触的部分,需求人工处理,能够借助一些第三方的比照东西。人工处理完毕后,完结兼并提交,才最终完结此次兼并。=======
分割线上方是当时分支的内容,下方是被兼并分支的改变内容。
7.5、变基rebase
把两个分支的修正内容兼并到一同的办法有两种:merge
和 rebase
,作用都是相同的,差异是rebase
的提交前史更简练,干掉了分叉,merge的提交前史更完好。
- 在
dev
上履行“git rebase master
”变基,将dev
分支上分叉的v7
、v8
生成补丁,然后在master
分支上运用补丁,发生新的v7'
、v8'
新的提交。 - 然后回到
master
分支,完结兼并git merge dev
,此刻的兼并便是快速兼并了。 - 最终的提交记载就没有分叉了。
$ git rebase master
$ git checkout master
$ git merge dev
08、标签办理
标签(Tags)指的是某个分支某个特守时刻点的状况,是对某一个提交记载的的固定“指针”引证。一经创立,不行移动,存储在作业区根目录下.git\refs\tags
。能够了解为某一次提交(编号)的别号,常用来标记版别。所以发布时,一般都会打一个版别标签,作为该版别的快照,指向对应提交commit
。
当项目达到一个要害节点,期望永远记住那个特别的提交快照,你能够运用 git tag
给它打上标签。比如咱们今日总算完结了V1.1版别的开发、测试,并成功上线了,那就可给今日最后这个提交打一个标签“V1.1”,便于版别办理。
默许标签是打在最新提交的commit上的,假如期望在指定的提交上打标签则带上提交编号(commit id):git tag v0.9 f52c633
指令 | 描绘 |
---|---|
git tag | 检查标签列表 |
git tag -l ‘a*’ | 检查称号是“a”最初的标签列表,带查询参数 |
git show [tagname] | 检查标签信息 |
git tag [tagname] | 创立一个标签,默许标签是打在最新提交的commit上的 |
git tag [tagname] [commit id] | 新建一个tag在指定commit上 |
git tag -a v5.1 -m’v5.1版别’ | 创立标签v5.1.1039 ,-a 指定标签名,-m 指定阐明文字 |
git tag -d [tagname] | 删去本地标签 |
git checkout v5.1.1039 | 切换标签,同切换分支 |
git push [remote] v5.1 | 推送标签,标签不会默许随代码推送推送到服务端 |
git push [remote] –tags | 提交一切tag |
假如要推送某个标签到长途,运用指令git push origin [tagname]
,或许,一次性推送全部到长途:git push origin --tags
注意:标签总是和某个commit挂钩。假如这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都能够看到这个标签。
# tag
$ git tag -a 'v1' -m'v1版别'
$ cat .git/refs/tags/v1
a2e2c9caea35e176cf61e96ad9d5a929cfb82461
# 检查标签列表
$ git tag
v1
09、懊悔药-怎样吊销改变?
发现写错了要回退怎样办?看看下面几种懊悔指令吧!
- ❓还没提交的怎样吊销? ——
checkout
、reset
- 还未提交的修正(作业区、暂存区)不想要了,用签出指令(checkout)进行吊销铲除。
- 或许用
checkout
的新版回滚指令reset
。
- ❓已提交但么有push的提交怎么吊销?——
reset
、revert
- ❓已push的提交怎么吊销?—— 同上,先本地吊销,然后强制推送
git push origin -f
,⚠️注意慎用! 记得先pull
获取更新。
9.1、懊悔指令
指令 | 描绘 |
---|---|
git checkout . | 吊销作业区的(未暂存)修正,把暂存区康复到作业区。不影响暂存区,假如没暂存,则吊销一切作业区修正 |
git checkout [file] | 同上,file 指定文件 |
git checkout HEAD . | 吊销作业区、暂存区的修正,用HEAD 指向的当时分支最新版别替换作业区、暂存区 |
git checkout HEAD [file] | 同上,file 指定文件 |
git reset | 吊销暂存区状况,同git reset HEAD ,不影响作业区 |
git reset HEAD [file] | 同上,指定文件file ,HEAD 可省掉 |
git reset [commit] | 回退到指定版别,清空暂存区,不影响作业区。作业区需求手动git checkout 签出 |
git reset –soft [commit] | 移动分支master 、HEAD 到指定的版别,不影响暂存区、作业区,需手动git checkout 签出更新 |
git reset –hard HEAD | 吊销作业区、暂存区的修正,用当时最新版 |
git reset –hard HEAD~ | 回退到上一个版别,并重置作业区、暂存区内容。 |
git reset –hard [commit] | 回退到指定版别,并重置作业区、暂存区内容。 |
git revert[commit] | 吊销一个提交,会用一个新的提交(原提交的逆向操作)来完结吊销操作,假如已push 则从头push 即可 |
-
git checkout .
、git checkout [file]
会铲除作业区中未增加到暂存区的修正,用暂存区内容替换作业区。 -
git checkout HEAD .
、git checkout HEAD [file]
会铲除作业区、暂存区的修正,用HEAD指向的当时分支最新版别替换暂存区、作业区。
# 只吊销作业区的修正(未暂存)
$ git checkout .
Updated 1 path from the index
# 吊销作业区、暂存区的修正
$ git checkout HEAD .
Updated 1 path from f951a96
9.2、回退版别reset
reset
是专门用来吊销修正、回退版别的指令,支撑的场景比较多,多种吊销姿态,所以参数组合也比较多。简略了解便是移动master
分支、HEAD
的“指针”地址,了解这一点就根本把握reset
了。
如下图:
- 回退版别
git reset --hard v4
或git reset --hard HEAD~2
,master
、HEAD
会指向v4
提交,v5
、v6
就被废弃了。 - 也能够从头康复到
v6
版别:git reset --hard v6
,便是移动master
、HEAD
的“指针”地址。
reset
有三种形式,对应三种参数:mixed
(默许形式)、soft
、hard
。三种参数的首要差异便是对作业区、暂存区的操作不同。
-
mixed
为默许形式,参数能够省掉。 - 只有
hard
形式会重置作业区、暂存区,一般用这个形式会多一点。
形式称号\ | 描绘 | HEAD的方位 | 暂存区 | 作业区 |
---|---|---|---|---|
soft | 回退到某一个版别,作业区不变,需手动git checkout
|
修正 | 不修正 | 不修正 |
mixed(默许) | 吊销暂存区状况,不影响作业区,需手动git checkout
|
修正 | 修正 | 不修正 |
hard | 重置未提交修正(作业区、暂存区) | 修正 | 修正 | 修正 |
穿梭前,用git log
能够检查提交前史,以便确认要回退到哪个版别。要重返未来,用git reflog
检查指令前史,以便确认要回到未来的哪个版别。
git reset [--soft | --mixed | --hard] [HEAD]
# 吊销暂存区
$ git reset
Unstaged changes after reset:
M R.md
# 吊销作业区、暂存区修正
$ git reset --hard HEAD
# 回退版别库到上一个版别,并重置作业区、暂存
$ git reset --hard HEAD~
# 回到原来的版别(康复上一步的吊销操作),并重置作业区、暂存
$ git reset --hard 5f8b961
# 检查一切前史提交记载
$ git reflog
ccb9937 (HEAD -> main, origin/main, origin/HEAD) HEAD@{0}: commit: 报表新增导入功用
8f61a60 HEAD@{1}: commit: bug:修正报表导出bug
4869ff7 HEAD@{2}: commit: 用户报表模块开发
4b1028c HEAD@{3}: commit: 财务报表模块开发完结
9.3、吊销提交revert
安全的吊销某一个提交记载,根本原理便是出产一个新的提交,用原提交的逆向操作来完结吊销操作。注意,这不同于reset
,reset
是回退版别,revert仅仅用于吊销某一次前史提交,操作是比较安全的。
如上图:
- 想吊销
v4
的修正,履行git revert v4
,会发生一个新的提交v-4
,是v4
的逆向操作。 - 一起更新
maser
、HEAD
“指针”方位,以及作业区内容。 - 假如已
push
则从头push
即可。
# revert吊销指定的提交,“-m”附加阐明
$ git revert 41ea42 -m'吊销对***的修正'
[main 967560f] Revert "123"
1 file changed, 1 deletion(-)
9.4、checkout/reset/revert总结
标题 \ 指令 | checkout | reset | revert |
---|---|---|---|
首要作用(吊销) | 吊销作业区、暂存区未提交修正 | 回退版别,重置作业区、暂存区 | 吊销某一次提交 |
吊销作业区 | git checkout [file] | git reset HEAD [file] | |
吊销作业区、暂存区 | git checkout HEAD [file] | git reset –hard HEAD [file] | |
回退版别 | git reset –hard [commit] | ||
安全性 | 只针对未提交修正,安全 | 如回退了已push 提交,不安全
|
安全 |
可看出reset
完全能够代替checkout
来履行吊销、回退操作,reset
本来也是专门用来干这个作业的,能够扔掉checkout
了(吊销的时分)。
10、作业中的Git实践
10.1、Git flow
Git flow(Git作业流程)是指软件项目中的一种Git分支办理模型,经过了很多的实践和优化,被认为是现代灵敏软件开发和DevOps(开发、技能运营和质量保证三者的交集)的最佳实践。Git flow首要流程及要害分支:原图地址-processon
✅主分支:master,安稳版别代码分支,对外能够随时编译发布的分支,不允许直接Push代码,只能恳求兼并(pull request),且只接受hotfix
、release
分支的代码兼并。
✅热修正分支:hotfix,针对线上紧急问题、bug修正的代码分支,修正完后兼并到主分支、开发分支。
- ① 切换到
hotfix
分支,从master
更新代码; - ② 修正bug;
- ③ 兼并代码到
dev
分支,在本地Git中操作即可; - ④ 兼并代码到
master
分支。
✅发版分支:release,版别发布分支,用于迭代版别发布。迭代开发完结后,兼并dev
代码到release
,在release
分支上编译发布版别,以及修正bug(守时同步bug修正到dev
分支)。测试完结后此版别能够作为发版运用,然后把安稳的代码push到master
分支,并打上版别标签。
✅开发分支:dev,开发版别分支,针对迭代任务开发的分支,日常开发原则上都在此分支上面,迭代完结后兼并到release分支,开发、发版两不误。
✅其他开发分支:dev-xxx,开发人员能够针对模块自己创立本地分支,开发完结后兼并到dev开发分支,然后删去本地分支。
10.2、金屋藏娇stash
当你正在dev
分支开发一个功用时,代码写了一半,忽然有一个线上的bug急需求马上修正。dev
分支Bug没写完,不便利提交,就不能切换到主分支去修正线上bug。Git提供一个stash
功用,能够把当时作业区、暂存区 未提交的内容“躲藏”起来,就像什么都没发生相同。
# 有未提交修正,切换分支时报错
$ git checkout dev
error: Your local changes to the following files would be overwritten by checkout:
README.md
Please commit your changes or stash them before you switch branches.
Aborting
# 躲藏
$ git stash
Saved working directory and index state WIP on main: 2bc012c s
# 检查被躲藏的内容
$ git stash list
stash@{0}: WIP on main: 2bc012c s
# 比较一下,什么都没有,一切都没有发生过!
$ git diff
# 去其他分支修正bug,修正完结回到当时分支,康复作业区
$ git stash pop
在上面示例中,有未提交修正,切换分支时报错。过错提示信息很明确了,commit
提交或stash
躲藏:Please commit your changes or stash them before you switch branches.
假如切换分支时,未提交修正的内容没有抵触,是能够成功切换的,未提交修正会被带过去。
指令 | 描绘 |
---|---|
git stash | 把未提交内容躲藏起来,包含未暂存、已暂存。 等以后康复现场后继续作业 |
git stash list | 检查一切被躲藏的内容列表 |
git stash pop | 康复被躲藏的内容,一起删去躲藏记载 |
git stash save “message” | 同git stash ,能够补白阐明message
|
git stash apply | 康复被躲藏的文件,可是躲藏记载不删去 |
git stash drop | 删去躲藏记载 |
当然这里先提交到本地也是能够的,仅仅提交不是一个完好的功用代码,而是残缺的一部分,影响也不大。
拣选提交cherry-pick
当有一个紧急bug,在dev
上修正完,咱们需求把dev
上的这个bug修正所做的修正“复制”到master
分支,但不想把整个dev兼并过去。为了便利操作,Git专门提供了一个cherry-pick
指令,让咱们能复制一个特定的提交到当时分支,而不管这个提交在哪个分支。
如上图,操作进程相当于将该提交导出为补丁文件,然后在当时HEAD
上重放,构成不管内容仍是提交阐明都一致的提交。
- 期望把
dev
分支上的v7
提交的内容兼并到master
,但不需求其他的内容。 - 在
master
分支上履行指令git cherry-pick v7
,会发生一个新的v7'
提交,内容和v7
相同。 - 一起更新
master
、HEAD
,以及作业区。
# 选择一个commit,兼并进当时分支
$ git cherry-pick [commit]
参考资料
- 博客园 | 深入浅出Git教程
- 山公都能懂的GIT入门
- 廖雪峰的GIT教程
- 电子书《ProGit-Git教程》
- Gitee码云的 Git 大全,真的挺全
- 灵敏进程实践-git代码分支办理标准
- 易百教程-Git教程?
- 在线Git学习+练习
- GUI Clients Git网站上的GUI东西列表
- Git常用指令调集
️版权声明:版权一切@安木夕,本文内容仅供学习,欢迎纠正、沟通,转载请注明出处!原文修正地址-语雀