1. Git是什么
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git原来是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
1.1 Git 与 SVN 区别
Git 不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。如果你是一个具有使用 SVN 背景的人,你需要做一定的思想转换,来适应 Git 提供的一些概念和特征。
Git
与SVN
区别点:
1、
Git
是分布式的,SVN
不是:这是Git
和其它非分布式的版本控制系统,2、
Git
把内容按元数据方式存储,而SVN
是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn、.cvs
等的文件夹里。3、
Git
分支和SVN
的分支不同:分支在SVN
中一点都不特别,其实它就是版本库中的另外一个目录。4、
Git
没有一个全局的版本号,而SVN
有:目前为止这是跟SVN
相比Git
缺少的最大的一个特征。5、
Git
的内容完整性要优于SVN
:Git
的内容存储使用的是SHA-1
哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。
2. Git安装
2.1 Linux下的Git
Git 的工作需要调用curl,zlib,openssl,expat,libiconv
等库的代码,所以需要先安装这些依赖工具。 在有yum
的系统上centOS或者有apt-get
的系统上(比如 Debian 体系),可以用下面的命令安装:
2.1.1 ubuntu安装
1 | $ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \ |
2.1.2 centOS安装
1 | $ yum install curl-devel expat-devel gettext-devel \ |
2.2 windows下的Git
在 Windows平台上安装 Git同样轻松,找到官网下载链接,点击下一步直接安装即可。
2.3 Git配置
Git 提供了一个叫做git config
的工具,专门用来配置或读取相应的工作环境变量。这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:
/etc/gitconfig
文件:系统中对所有用户都普遍适用的配置。若使用git config
时用--system
选项,读写的就是这个文件。~/.gitconfig
文件:用户目录下的配置文件只适用于该用户。若使用git config
时用--global
选项,读写的就是这个文件。- 当前项目的
Git
目录中的配置文件(也就是工作目录中的.git/config
文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config
里的配置会覆盖/etc/gitconfig
中的同名变量。
在 Windows 系统上,Git 会找寻用户主目录下的 .git/config
文件。主目录即 $HOME 变量指定的目录,一般都是 C:\Documents and Settings\$USER。
此外,Git 还会尝试找寻 /etc/gitconfig
文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位。
2.3.1 用户信息
为了方便后续Git能跟踪到谁做了修改,我们需要设置对应的用户名与邮箱地址。 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20$ git config --global user.name "wuwenjie"
$ git config --global user.email 1229413537@qq.com
$ git config --list
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
http.sslbackend=openssl
http.sslcainfo=D:/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.email=1229413537@qq.com
user.name=wuwenjie
git config
命令的--global
参数,表示使用的这台机器上所有的 Git 仓库都会使用这个配置
2.3.2 git配置ssh
git是现在代码管理的一个常用工具,采用两种传输方式 http
和 ssh
。SSH
比较安全可靠,也不需要每次都输入账号密码,所以我们在使用git时一般采用ssh。
windows版本:
- windows打开Gitbash(linux打开终端)输入 如果你看到一下输出,那么说明你已经有ssh秘钥 (以.pub结尾的文件)
1
$ ls -al ~/.ssh
1
2
3
4
5
6total 24
drwxr-xr-x 1 Administrator 197121 0 Sep 23 15:25 .
drwxr-xr-x 1 Administrator 197121 0 Sep 23 15:07 ..
-rw-r--r-- 1 Administrator 197121 3389 Sep 23 15:07 id_rsa
-rw-r--r-- 1 Administrator 197121 750 Sep 23 15:07 id_rsa.pub
-rw-r--r-- 1 Administrator 197121 1458 Sep 23 15:25 ssh.ppk 如果你不想用原来的秘钥或者没有秘钥的话,直接进行下一步生成ssh公钥秘钥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24ssh-keygen -t rsa -C 邮箱
//如下:
trluper@trluper-virtual-machine:~$ ssh-keygen -t rsa -C "1229413537@qq.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/trluper/.ssh/id_rsa):
Created directory '/home/trluper/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/trluper/.ssh/id_rsa
Your public key has been saved in /home/trluper/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:1Cj60kKeZzc8eMn1G09kN65qxVQ4FhyiKwumBElPf6I 1229413537@qq.com
The key's randomart image is:
+---[RSA 3072]----+
| . . ..o+ |
|. + . o. .= . |
| o . o..o.. . o |
| . ..oo . . |
| Eoo .S.. o o..|
| .oo+.+oo . =...|
| .= *.O + .. |
| = o o . =. |
| ..o.. |
+----[SHA256]-----+将公钥复制到github上,使用
ssh -T git@github.com
验证是否成功,成功会出现以下语句1
2trluper@trluper-virtual-machine:~$ ssh -T git@github.com
Hi trluper! You've successfully authenticated, but GitHub does not provide shell access.
附加:如果上面的
ssh -T git@github.com
验证成功,但是git clone时出现错误:则说明本节git仓库没有没有和这个ssh key关联,则依次执行:
1
2
3 trluper@trluper-virtual-machine:/home/CPP_project$ git clone git@github.com:qinguoyi/TinyWebServer.git
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.输出:
1
2
3 //查看密钥运行
root@trluper-virtual-machine:/home/trluper/.ssh
root@trluper-virtual-machine:/home/trluper/.ssh//把ssh添加到你的账号
1
2
3 SSH_AUTH_SOCK=/tmp/ssh-XXXXXX8U3b13/agent.259910; export SSH_AUTH_SOCK;
SSH_AGENT_PID=259911; export SSH_AGENT_PID;
echo Agent pid 259911;输出下述语句则说明添加成功
1
2 root@trluper-virtual-machine:/home/trluper/.ssh
root@trluper-virtual-machine:/home/trluper/.ssh
1 Identity added: /home/trluper/.ssh/id_rsa (1229413537@qq.com)
3. git工作流程
git一般工作流程如下:
- 克隆 Git 资源作为工作目录。
- 在克隆的资源上添加或修改文件。
- 如果其他人修改了,你可以更新资源。
- 在提交前查看修改。
- 提交修改。
- 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。
4. git三个区和三个状态
我们先来理解下 Git 工作区、暂存区和版本库概念:
- 工作区:就是你在电脑里能看到的目录。
- 暂存区:英文叫
stage
或index
。一般存放在.git
目录下的index
文件(.git/index
)中,所以我们把暂存区有时也叫作索引(index)。 版本库:工作区有一个隐藏目录
.git
,这个不算工作区,而是Git
的版本库。存储着所有提交的版本快照,并由当前分支引用的指针HEAD指向该分支最新一条提交- 图中左侧为工作区,右侧为版本库。在版本库中标记为
index
的区域是暂存区stage/index
,标记为master
的是master
分支所代表的目录树。 - 图中我们可以看出此时
HEAD
实际是指向master
分支的一个游标
。所以图示的命令中出现HEAD
的地方可以用master
来替换。 - 图中的
objects
标识的区域为Git
的对象库,实际位于.git/objects
目录下,里面包含了创建的各种对象及内容。 - 当对工作区修改(或新增)的文件执行
git add
命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。 - 当执行提交操作
git commit
时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即master
指向的目录树就是提交时暂存区的目录树。 - 当执行
git reset HEAD
命令时,暂存区的目录树会被重写,被master
分支指向的目录树所替换,但是工作区不受影响。 - 当执行
git rm --cached <file>
命令时,会直接从暂存区删除文件,工作区则不做出改变。 - 当执行
git checkout
. 或者git checkout -- <file>
命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区中的改动。 当执行
git checkout HEAD
. 或者git checkout HEAD <file>
命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
5. Git创建仓库
可以使用一个已经存在的目录作为Git
仓库。Git
使用git init
命令来初始化一个Git
仓库,Git
的很多命令都需要在Git
的仓库中运行,所以git init
是使用Git
的第一个命令。
在执行完成git init
命令后,Git
仓库会生成一个.git
目录,该目录包含了资源的所有元数据,其他的项目目录保持不变
当前目录即为仓库:使用当前目录作为 Git 仓库,我们只需使它初始化。
该命令执行完后会在当前目录生成一个 .git 目录,内部含有的内容如上所示,没有1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16git init
//示例
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest
$ git init
Initialized empty Git repository in C:/Users/Trluper/Desktop/gitTest/.git/
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ ls -al
total 8
drwxr-xr-x 1 Trluper 197121 0 Mar 13 12:43 ./
drwxr-xr-x 1 Trluper 197121 0 Mar 13 12:42 ../
drwxr-xr-x 1 Trluper 197121 0 Mar 13 12:43 .git/
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ cd .git/
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest/.git (GIT_DIR!)
$ ls
HEAD config description hooks/ info/ objects/ refs/index
是因为我们还没用到暂存区,如果git add filename
则就会创建一个index
目录。使用我们指定目录作为Git仓库。
初始化后,会在1
git init newrepo
newrepo
目录下会出现一个名为.git
的目录,所有Git
需要的数据和资源都存放在这个目录中。
如果当前目录下有几个文件想要纳入版本控制,需要先用git add
命令告诉Git
开始对这些文件进行跟踪,然后提交: 1
2
3
4//以下命令将目录下以 .c 结尾及 README 文件提交到仓库中。
$ git add *.c
$ git add README
$ git commit -m '初始化项目版本''
,Windows 系统,commit 信息使用双引号"
。 >所以在 git bash 中git commit -m '提交说明'
这样是可以的,在 Windows 命令行中就要使用双引号 >git commit -m "提交说明"
。
6. Git的基本操作
Git 的工作就是创建和保存你项目的快照及与之后的快照进行对比。Git 常用的是以下 6 个命令:git clone、git push、git add 、git commit、git checkout、git pull
,后面我们会详细介绍。
workspace
:工作区staging area
:暂存区/缓存区local repository
:版本库或本地仓库remote repository
:远程仓库
6.1 git clone
我们使用git clone
从现有Git
仓库中拷贝项目(类似svn checkout
).克隆仓库的命令格式为:git clone <repo>
。
要克隆Ruby
语言的Git
代码仓库Grit
,可以用下面的命令: 1
$ git clone git://github.com/schacon/grit.git
6.2 本地仓库操作
下表列出了有关创建与提交你的项目的快照的命令:
命令 | 说明 |
---|---|
git add |
添加文件到暂存区 |
git status |
查看仓库当前的状态,显示有变更的文件。 |
git diff |
比较文件的不同,即暂存区和工作区的差异。 |
git commit |
提交暂存区到本地仓库。 |
git reset |
回退版本。 |
git rm |
将文件从暂存区和工作区中删除。 |
git mv |
移动或重命名工作区文件。 |
6.2.1 git add命令
git add
命令可将该文件添加到暂存区,其形式可为: 1
2
3
4
5
6添加一个或多个文件到暂存区:
git add [file1] [file2] ...
添加指定目录到暂存区,包括子目录:
git add [dir]
添加当前目录下的所有文件到暂存区:
git add .1
2Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git add test1
6.2.2 git status命令
git status
命令用于查看在你上次提交之后是否有对文件进行再次修改。 1
2
3
4
5
6
7
8
9Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: test1/test1.txt-s
参数来获得简短的输出结果: 1
2
3
4
5
6
7Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ echo "trluper" > test1/test1.txt
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git status -s
AM test1/test1.txt
?? test1.txtM
:表示这个文件在我们将它添加到缓存之后又有改动。 - ??
:表示改文件未添加到缓存区
6.2.3 git diff命令
git diff
命令显示已写入暂存区和已经被修改但尚未写入暂存区文件的区别。git diff 有两个主要的应用场景:
- 尚未缓存的改动:
git diff
- 查看已缓存的改动:
git diff --cached
- 查看已缓存的与未缓存的所有改动:
git diff HEAD
- 显示摘要而非整个
diff:git diff --stat
1 | Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master) |
6.2.4 git commit命令
git commit
命令将暂存区内容添加到本地仓库中。 1
2
3
4
5
6Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git commit -m "commit test 2"
[master (root-commit) b795d59] commit test 2
2 files changed, 2 insertions(+)
create mode 100644 test1.txt
create mode 100644 test1/test1.txt
-m
:m
为message
的缩写,表示为后面要接的提交描述,如果没有加-m
描述,则git会打开一个Vim编辑器让你填写提交信息-a
:如果你觉的不要填写提交信息,那么-a
选项跳过这一步
6.2.5 git reset命令
git reset
命令用于回退版本,可以指定退回某一次提交的版本。语法格式如下: 1
2
3git reset [--soft | --mixed | --hard] [HEAD/commit_id]
//回退指定版本号
git reset -hard (版本号) //版本号没必要写全,前几位就可以了,Git会自动去找,版本号通过git log --pretty=oneline获取
--hard
:工作区、暂存区、本地仓库都会回滚到对应commit-id上–-mixed
为默认的,可以不用带该参数。使用该参数工作区代码不会受到影响,但是暂存区、本地仓库区的代码已经回滚到了YY对应的commit-id上。--soft
:工作区和暂存区的代码不会受到影响,但是本地仓库的代码会回滚到YY对应的commit-id上
示例: 1
2
3
4
5
6
7
8Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git log --pretty=oneline
450f4d7914f2db54bdab2eea422119e1fea7fafa (HEAD -> master) 第二次commit
b795d59de32dd11f307ecefa32b51c7dd8b901af commit test 2
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git reset --hard HEAD^
HEAD is now at b795d59 commit test 2
注意:谨慎使用 –-hard
参数,它会删除回退点之前的所有日志提交记录。 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest ((8692a93...))
$ git log --pretty=oneline
8692a9397fb6fd23a262eb8f38997b549064a017 (HEAD) fix conflict
0bd22ddc1e7387bd4e97effa0a463056ce7be0dd master修改
//--hard回退到master修改
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest ((8692a93...))
$ git reset --hard 0bd22ddc1e7387bd4e97effa0a463056ce7be0dd
HEAD is now at 0bd22dd master修改
//再次查看日志:fix conflict记录已经没有了
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest ((0bd22dd...))
$ git log --pretty=oneline
0bd22ddc1e7387bd4e97effa0a463056ce7be0dd (HEAD) master修改
HEAD说明
也可以
1
2
3
4
5 HEAD 表示当前版本
HEAD^ 上一个版本
HEAD^^ 上上一个版本
HEAD^^^ 上上上一个版本
以此类推...~数字
表示
1
2
3
4
5 HEAD~0 表示当前版本
HEAD~1 上一个版本
HEAD~2 上上一个版本
HEAD~3 上上上一个版本
以此类推...
6.2.6 git revert命令
上面的git reset [commit_id]
的--hard
参数太极端直接清除了[commit_id]
之前的提交记录,而对应参数--mixed --soft
虽然不会清除记录,但没有更改版本库的内容,即你还得修改后手动commit
一次。
revert
命令不这样做,他不会清除之前的提交日志记录,而是自动的commit
一次最新的提交
6.2.7 git rm命令
git rm
命令用于删除文件。
如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 Changes not staged for commit 的提示。
git rm
删除文件有以下几种形式:
- 将文件从暂存区和工作区中删除:
- 如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f。
1
git rm -f <file>
- 如果想把文件从暂存区域移除,但仍然希望保留在当前工作目录中,换句话说,仅是从跟踪清单中删除,使用
--cached
选项即可:1
git rm --cached <file>
- 如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f。
6.2.8 git mv命令
git mv
命令用于移动或重命名一个文件、目录或软连接。 1
git mv [file] [newfile]
1
2
3
4
5
6
7
8
9Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git mv -f README.txt README.md
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: README.txt -> README.md-f
:若新文件名已经存在,但还是要重命名它,可以使用 -f
参数
6.3 提交日志
命令 | 说明 |
---|---|
git log |
查看历史提交记录 |
git blame <file> |
以列表形式查看指定文件的历史修改记录 |
6.3.1 git log命令
在使用 Git 提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,我们可以使用 git log 命令查看。 1
2
3
4
5
6
7
8
9
10
11
12
13Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git log --oneline
21ab31a (HEAD -> master) 第三次提交
b795d59 commit test 2
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git log --pretty=online
fatal: invalid --pretty format: online
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git log --pretty=oneline
21ab31a605efea7f4b3f8ebb47aecee82311a534 (HEAD -> master) 第三次提交
b795d59de32dd11f307ecefa32b51c7dd8b901af commit test 2
- 使用
--pretty=oneline
或者--oneline
来查看历史记录的简洁的版本,含有commit
提交id,哈希生成 - 用
--graph
选项,查看历史中什么时候出现了分支、合并 - 可以用
--reverse
参数来逆向显示所有日志
6.3.2 git blame命令
如果要查看指定文件的修改记录可以使用 git blame 命令,格式如下: 1
git blame <file>
1
2
3
4Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git blame README.md
88c273c5 README.md (wuwenjie 2023-03-13 18:55:00 +0800 1) 后缀名改了,为.md
21ab31a6 README.txt (wuwenjie 2023-03-13 18:42:25 +0800 2) 这是README文件,后缀还没改,为.txt
6.4 远程操作
命令 | 说明 |
---|---|
git remote |
远程仓库操作 |
git fetch |
从远程获取代码库 |
git pull |
下载远程代码并合并 |
git push |
上传远程代码并合并 |
6.4.1 git remote
命令
git remote
命令用于在远程仓库的操作,其有如下操作:
git remote add [shortname] [url]
:添加远程版本库,其中[shortname]为别名,后续对改远程仓库的操作可以通过别名来使用1
2Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git remote add trluperLearnGit https://github.com/trluper/Trluper_LearnGit.git-v
:显示当前所有的远程仓库git remote -v
1
2
3
4Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git remote -v
trluperLearnGit https://github.com/trluper/Trluper_LearnGit.git (fetch)
trluperLearnGit https://github.com/trluper/Trluper_LearnGit.git (push)git remote show
:显示某个远程仓库的信息:1
2
3
4
5
6
7
8
9
10Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git remote show
trluperLearnGit
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git remote show trluperLearnGit
* remote trluperLearnGit
Fetch URL: https://github.com/trluper/Trluper_LearnGit.git
Push URL: https://github.com/trluper/Trluper_LearnGit.git
HEAD branch: (unknown)git remote rm name
:删除远程仓库git remote rename old_name new_name
: 修改远程仓库名
6.4.3 git push 命令
git push
命令用于从将本地的分支版本上传到远程并合并。命令格式如下 1
2
3git push <远程主机名> <本地分支名>:<远程分支名>
//如果本地分支名与远程分支名相同,则可以省略冒号:
git push <远程主机名> <本地分支名>
示例: 1
2
3
4
5
6
7
8
9
10Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git push trluperLearnGit master:master
Enumerating objects: 10, done.
Counting objects: 100% (10/10), done.
Delta compression using up to 8 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (10/10), 920 bytes | 460.00 KiB/s, done.
Total 10 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/trluper/Trluper_LearnGit.git
* [new branch] master -> master--force
:本地版本与远程版本有差异,但又要强制推送可以使用 --force 参数: 1
git push --force trluperLearnGit master:trluper
--delete
:删除主机的分支可以使用 --delete 参数(一般不使用)
注意:一般来说在实际开发中,我们总会在远程仓库建立自己的分支,而不是直接
push
到master分支,这样push
到自己分支,管理者看完修改对比并同意后才合并到master
分支,这才是正确的做法
6.4.2 git fetch
命令
git fetch
命令用于从远程获取代码库。因为git fetch
不会改变本地仓库的状态,该命令执行完后需要执行 git merge
远程分支到你本地仓库所在的分支。命令格式
git fetch 实际所做的工作是将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态
1 | git fetch shortname |
git fetch
:改命令告诉 Git 去远程仓库获取它有你没有的数据。,下面的88c273c..54788d2 master -> trluperLearnGit/master
表示确实有新数据可获取1
2
3
4
5
6
7
8
9Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git fetch trluperLearnGit
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 766 bytes | 40.00 KiB/s, done.
From https://github.com/trluper/Trluper_LearnGit
88c273c..54788d2 master -> trluperLearnGit/mastergit merge trluperLearnGit/master
然后执行与本地指定分支合并查看一下是否更改了工作区的:1
2
3
4
5
6Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git merge trluperLearnGit/master
Updating 88c273c..54788d2
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)1
2
3
4
5Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ cat README.md
后缀名改了,为.md
这是README文件,后缀还没改,为.txt
我在github上修改,测试git fetch
6.4.3 git pull命令
git pull
命令用于从远程获取代码并合并本地的版本。就是将上面的git fetch
和git merge
合并·到了一起。一般来说使用pull
较多
git pull [shortname] [远程仓库分支]:[本地仓库分支]
1
2
3
4
5
6
7
8
9
10
11
12
13
14Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git pull trluperLearnGit trluper:master
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 687 bytes | 42.00 KiB/s, done.
From https://github.com/trluper/Trluper_LearnGit
54788d2..20be99d trluper -> master
* [new branch] trluper -> trluperLearnGit/trluper
warning: fetch updated the current branch head.
fast-forwarding your working tree from
commit 54788d2727502d34e5e214c2ce08853ac628a6f5.
Already up to date.
7. Git的分支管理
几乎每一种版本控制系统都以某种形式支持分支,一个分支代表一条独立的开发线。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。Git
分支实际上是指向更改快照的指针。有人把Git
的分支模型称为必杀技特性,而正是因为它,将Git
从版本控制系统家族里区分出来。
在 Git 里,master
分支叫主分支。HEAD
严格来说不是指向提交,而是指向 master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。
7.1 git branch创建分支
1 | git branch (branchname) |
没有参数时,git branch
会列出你在本地的分支。当你执行git init
的时候,默认情况下Git
就会为你创建master
主分支。如果我们要手动创建一个分支。执行git branch (branchname)
即可。 1
2
3
4$ git branch testing
$ git branch
* master
testing
7.2 git checkout切换分支
格式: 1
git checkout [commit_id/分支名称]
commit
提交都会生成哈希索引,默认HEAD指向最新的提交记录,checkout
其实就是改变HEAD
的指向,从而达到改变切换分支的目的。但他不仅仅只有改变分支的作用,只要你想切换到任一提交记录都可以: 1
2
3
4
5
6
7
8
9
10
11
12
13Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git log --pretty=oneline
65eb23309a8650f462f61f14ec661219072f2a8f (HEAD -> master) checkout
8692a9397fb6fd23a262eb8f38997b549064a017 fix conflict
0bd22ddc1e7387bd4e97effa0a463056ce7be0dd master修改
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git checkout 8692a9397fb6fd23a262eb8f38997b549064a017
Note: switching to '8692a9397fb6fd23a262eb8f38997b549064a017'.
Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest ((8692a93...))
$
用
git checkout (branch)
切换到我们要修改的分支,checkout
的工作原理就只是修改HEAD
指针的指向。每个提交记录是独立的,其工作区间、暂存区和版本库的内容不与其他记录共享,即当切换到一个提交记录时,就会显示改记录的内容。
1 | $ ls |
当我们切换到testing
分支的时候,我们添加的新文件 test.txt
被移除了。切换回master
分支的时候,它们又重新出现了。
7.4 合并分支
一旦某分支有了独立内容,你终究会希望将它合并回到你的主分支。 你可以使用以下命令将任何分支合并到当前分支中去:git merge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15$ git branch
* master
newtest
$ ls
README test.txt
$ git merge newtest
Updating 3e92c19..c1501a2
Fast-forward
runoob.php | 0
test.txt | 1 -
2 files changed, 1 deletion(-)
create mode 100644 runoob.php
delete mode 100644 test.txt
$ ls
README runoob.phpnewtest
分支合并到主分支去,那么test.txt
文件被删除,runoob.php
被添加到主分支
7.5 删除分支
删除分支只需加个-d
即可:git branch -d (branchname)
1
2
3
4
5
6
7$ git branch
* master
testing
$ git branch -d testing
Deleted branch testing (was 85fc7e7).
$ git branch
* master
7.6 详解分支管理
假如你有两个分支master
和dev
:
1、当你只是
checkout
切换一个分支,而对两个分支都没修改(在切换分支时一旦在工作区修改git会要求你在切换前commit
),那么各分支状态如下:2、现在你切换到了dev,并修改了三次,
commit
了三次,那么在本地仓库(版本库)会生成三次的哈希索引,且其分支记录指针图示如下:- 3、现在有另一种情况,你在
dev
修改,另一位同事对master
分支做出修改,这时候就可能出现潜在问题,出现合并冲突:- 如果你们的修改没有出现合并冲突,那么很好,你们可以愉快的执行
git merge dev
操作 - 但如果你能出现冲突了(比如说修改了同一份文件、master创建一份新的代码文价),你必须手动解决冲突,再去合并,非常好的一点是,git会提示冲突出现的位置。
- 如果你们的修改没有出现合并冲突,那么很好,你们可以愉快的执行
举例有一个
test.txt
文件,在mater
添加了master:修改
,在test
分支添加test:修改
,都各自commit,在执行合并操作时出现合并冲突:1
2
3
4
5Trluper@DESKTOP-67ADUGH MINGW64 ~/Desktop/gitTest (master)
$ git merge test
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
合并冲突:冲突的产生是因为在合并的时候,不同分支修改了相同的位置。所以在合并的时候git不知道哪个到底是你想保留的,所以就提出疑问(冲突提醒)让你自己手动选择想要保留的内容,从而解决冲突。 解决冲突:
- (一股脑)使用merge命令合并分支,解决完冲突,执行git add .和git commit -m'fix conflict'。这个时候会产生一个commit。
- (交互式)使用rebase命令合并分支,解决完冲突,执行git add .和git rebase --continue,不会产生额外的commit。这样的好处是,‘干净’,分支上不会有无意义的解决分支的commit;坏处,如果合并的分支中存在多个commit,需要重复处理多次冲突。
8 git回滚一次错误合并
在git种支持回滚的操作主要有三个checkout、reset、revert
- 三个回滚操作在我们错误提交还未
push
时具有重要作用,支持我们回滚版本、版本管理强。 - 三个操作的具体见上面章节。
9 git的merge和rebase区别
merge
和rebase
都是用来合并分支的。
- 1.采用
merge
和rebase
后,git log的区别:- 执行
merge
命令的分支会生成merge
的提交记录, - 而
rebase
不会生成merge记录,但会保留所有的commit
记录,话句话说就是将另一个分支作为当前分支的基线。(即rebase: 合体
merge: 脚手相连,肚皮是独立的
)
- 执行
merge
和rebase
应用场景:merge
一般用在master
这种公共分支上。在多人开发同一个项目时,如果多人的开发分支有一定的命名规范,比如需求的版本号,那么在排查问题或者追溯需求时,会很方便;保存的日志记录轨迹清晰,回滚方便- 一般
rebase
基本法则是只对自己的的分支做,在自己的分支上若有多次提交,可以合并为一次提交,并强推上去,这样的话将自己的分支合入公共分支master的时候,分支树也很简明
1 | 在dev分支执行下面语句的意思: |
扩展:当你本地仓库落后于远程仓库进行
commit
,然后pull
, 那会多生成一条merge
记录, 这是非常错误的:
- 情况1:如果
remote
分支超前于本地分支,并且本地分支没有任何commit
的,直接从remote
进行pull
操作,默认会采用fast-forward
模式,这种模式下,并不会产生合并节点,也就是说不会产生多余的记录- 情况2:如果,本地先
commit
后再去pull
,那么此时,remote
分支和本地会分支会出现分叉,这个时候使用pull
操作拉取更新时,就会进行分支合并,产生合并节点和log
记录
关键是看自己本地有没有commit
,因为commit
已经进入了本地仓库了,是会被检测到,并记录的
应该要解决第二种情况:使用git pull --rebase
,使用rebase
合并,避免产生记录
因此一个合作项目的提交一般是这样的:(假设本地dev,远程自己的分支也是dev,远程主分支是master)
- 从远程master拉取:
git pull --reabse [shortname] master
- 本地commit:
git add .
;git commit -m "dev"
- 看是否有冲突,有冲突解决冲突
- push到远程dev分支:
git push Trluper dev
- 在远程仓库请求合并
文章来源:菜鸟教程