1. 引言
单人开发中需要进行版本管理以利于开发进度的配置 多人开发过程中,不仅需要版本管理还需进行多人协同控制。
2. 介绍
Git时一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。起初时为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。
3. 安装
4. 架构
版本库:工作区中有一个隐藏目录
.git这个目录不属于工作区,而是git的版本库,是git管理的所有内容暂存区:版本库中包含有一个临时区域,保存下一步需要提交的文件
分支:版本库中包含若干分支,提交的文件存储在分支中
5. 仓库
对应的就是一个目录,这个目录中所有文件都被git管理起来。 以后会将一个 项目的根目录,作为仓库 仓库中每个文件的改动都由git跟踪
5.1 新建仓库 git init
选择一个目录,执行 **git init**
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test$ git initInitialized empty Git repository in G:/code_workspace/git_test/.git/cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test (master)
6. 基本操作
6.1 查看仓库状态 git status
6.2 暂存 git add
执行 **git add** 将工作区文件存入暂存区
add . 和 add *的区别
git add .会把本地所有untrack的文件都加入暂存区,并且会根据.gitignore做过滤,但是git add *会忽略.gitignore把任何文件都加入
.gitignore 忽略文件
vim .gitignore
.gitignore中输入不想提交的文件名
例如不像提交 settings.py 文件
vim .gitignore
settings.py
:wq!
6.3 提交文件 git commit -m(massage) "描述信息"
执行 git commit -m “” 作用是将暂存区的文件存入分支,形成一个版本
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test (master)
$ git commit -m "add 1,2.md"
[master (root-commit) e107a16] add 1,2.md
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 1.md
create mode 100644 2.md
7. 远程仓库
多人协同时,每个开发人员在自己的本地仓库维护版本,远程仓库共享合并代码,
7.1 远程仓库工作模式
7.2 远程仓库选型
7.3 新建连接远程仓库 git remote <name> <address>
在github上新建repository
点击code-> use https 复制远程仓库地址
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test (master)
$ git remote add origin https://github.com/ck-wobbuffet/git_test.git
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test (master)
$ git remote -v
origin https://github.com/ck-wobbuffet/git_test.git (fetch)
origin https://github.com/ck-wobbuffet/git_test.git (push)
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test (master)
$ git pull origin master --allow-unrelated-histories
From https://github.com/ck-wobbuffet/git_test
* branch master -> FETCH_HEAD
Merge made by the 'recursive' strategy.
README.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 README.md
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test (master)
$ git push origin master
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 12 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 488 bytes | 488.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/ck-wobbuffet/git_test.git
6a05bf3..9434888 master -> master
报错 fatal: refusing to merge unrelated histories
因为我将远程连接到本地的子目录了。(重名冲突)
$ git pull origin master
fatal: refusing to merge unrelated histories
解决方案:
在你操作命令后面加 --allow-unrelated-histories
7.4 克隆远程仓库 git clone
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test (master)
$ git clone https://github.com/ck-wobbuffet/git_test.git
Cloning into 'git_test'...
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 8 (delta 1), reused 5 (delta 1), pack-reused 0
Unpacking objects: 100% (8/8), 1.03 KiB | 1024 bytes/s, done.
7.5 修改上传到远程仓库 git push 下载更新到本地 git pull
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test (master)
$ cd git_test/
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: 2.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
222.md
3.md
no changes added to commit (use "git add" and/or "git commit -a")
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git add .
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git commit -m "add 3, del 2, add 222"
[master c7c812a] add 3, del 2, add 222
2 files changed, 0 insertions(+), 0 deletions(-)
rename 2.md => 222.md (100%)
create mode 100644 3.md
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git push origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 241 bytes | 241.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/ck-wobbuffet/git_test.git
9434888..c7c812a master -> master
7.6 命令操作
| git remote add <标识名name>(origin) |
本地关联远程仓库 |
|---|---|
| git push <标识名> |
本地上传到远程 |
| git pull <标识名> |
远程下载到本地 |
| git clone |
远程复制到本地,自动形成一个本地仓库 |
8. 分支
8.1 什么是分支
分支 是一个个版本的最终存储位置 分支 就是一条时间线,每次 git commit 形成一个个版本,一个个版本依次存储在一个个提交点上。
8.2 分支基操
8.2.1 查看分支 git branch
查看当前仓库的分支 git branch 仓库中默认只有 master** 分支 执行 git commit** 时,默认是在 master 分支上保存版本
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git branch
* master
8.2.2 创建分支 git branch <name>
一般不会轻易在master分支上操作 新建一个开发用的分支,在此分支上操作记录 当代码没有问题时才将开发分支上成熟的版本代码添加到master分支上 即保证开发过程中可以及时记录版本,又保证master分支上每个提交点都是稳健版本。
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git branch dev
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git branch
dev
* master
8.2.3 切换分支 git checkout <name>
默认情况下都是 * master 用 git checkout dev指令切换到dev分支,后续的git commit操作便会在dev分支上新建版本(建点)
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git checkout dev
Switched to branch 'dev'
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (dev)
$ git branch
* dev
master
在dev分支下新建 5.txt 文件并提交文件,此时本地仓库中有 5.txt
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (dev)
$ git add .
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (dev)
$ git commit -m "add 5.txt"
[dev 2d61a7d] add 5.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 5.txt
切换到 master 分支,此时本地仓库中没有 5.txt
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (dev)
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
8.3 新建分支细节
新建分支时,新分支默认有哪些内容? 分支中包含哪些次提交?
8.3.1 新分支初始内容
每个分支都有一个指针,新建一个分支,首先是新建一个指针; 而且新分支的指针会和当前分支指向 同一个提交点 新分支包含的提交点就是从第一个提交点到分支指针指向的提交点。
8.3.2 多分支走向
在master和dev分支分别进行 git add 和 git commit
8.3.3分支提交日志 git log --oneline
查看分支的提交日志,进而看到分支中提交点的详细情况。
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git log --oneline
c7c812a (HEAD -> master, origin/master, origin/HEAD) add 3, del 2, add 222
9434888 Merge branch 'master' of https://github.com/ck-wobbuffet/git_test
6a05bf3 Initial commit
e107a16 add 1,2.md
git log 查看详细日志信息
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (dev)
$ git log
commit 2d61a7d9a3747b3c0d0737a310875c77e6fa117f (HEAD -> dev)
Author: chgken <chgken@users.noreply.github.com>
Date: Wed Aug 5 15:25:51 2020 +0800
add 5.txt
commit bc7302c4f444f72bd2b3d693d9d9115b4f6f4551
Author: chgken <chgken@users.noreply.github.com>
Date: Wed Aug 5 15:25:00 2020 +0800
change 3.md
commit c7c812a1c3fdafc6959820377cdfda3685f09593 (origin/master, origin/HEAD, master)
Author: chgken <chgken@users.noreply.github.com>
Date: Wed Aug 5 11:40:28 2020 +0800
add 3, del 2, add 222
commit 9434888adafad1c57842c87604174ab6270e0340
Merge: e107a16 6a05bf3
Author: chgken <chgken@users.noreply.github.com>
Date: Wed Aug 5 11:30:10 2020 +0800
:
8.4 分支合并 git merge
两个分支内容的合并 git merge
** **合并分支a 合并的方式有两种:快速合并 和 三方合并
8.4.1 快速合并
如果分支A当前的修改是完全基于分支B的修改而来,则B分支合并A分支,就是移动指针即可。

在master分支没有新改动commit的情况下,在dev分支有新的commit,此时切换到master分支
输入 git merge dev 将dev合并到当前分支master
此时合并是 fast merge
8.4.2 三方合并
如果master分支和dev分支都有新的提交,这是仅仅移动一个指针会丢失信息。
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (dev)
$ git log --oneline
85c559d (HEAD -> dev) modify 5.txt
a9d75a9 (dev2) modify 5.txt
2d61a7d add 5.txt
bc7302c change 3.md
c7c812a (origin/master, origin/HEAD) add 3, del 2, add 222
9434888 Merge branch 'master' of https://github.com/ck-wobbuffet/git_test
6a05bf3 Initial commit
e107a16 add 1,2.md
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (dev)
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git log --oneline
fd0d0d2 (HEAD -> master) add 6.md
c7c812a (origin/master, origin/HEAD) add 3, del 2, add 222
9434888 Merge branch 'master' of https://github.com/ck-wobbuffet/git_test
6a05bf3 Initial commit
e107a16 add 1,2.md
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git merge dev
Merge made by the 'recursive' strategy.
3.md | 2 ++
5.txt | 2 ++
2 files changed, 4 insertions(+)
create mode 100644 5.txt
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git log --oneline
fd4b5b3 (HEAD -> master) Merge branch 'dev'
fd0d0d2 add 6.md
85c559d (dev) modify 5.txt
a9d75a9 (dev2) modify 5.txt
2d61a7d add 5.txt
bc7302c change 3.md
c7c812a (origin/master, origin/HEAD) add 3, del 2, add 222
9434888 Merge branch 'master' of https://github.com/ck-wobbuffet/git_test
6a05bf3 Initial commit
e107a16 add 1,2.md
此时合并显示的是Merge made by the ‘recursive’ strategy.
使用 git log --oneline --graph 可以看到简约的分支合并图
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git log --oneline --graph
* fd4b5b3 (HEAD -> master) Merge branch 'dev'
|\
| * 85c559d (dev) modify 5.txt
| * a9d75a9 (dev2) modify 5.txt
| * 2d61a7d add 5.txt
| * bc7302c change 3.md
* | fd0d0d2 add 6.md
|/
* c7c812a (origin/master, origin/HEAD) add 3, del 2, add 222
* 9434888 Merge branch 'master' of https://github.com/ck-wobbuffet/git_test
|\
| * 6a05bf3 Initial commit
* e107a16 add 1,2.md
8.4.3 分支合并冲突
两个分支进行合并,但他们含有对同一个文件的i需改,则在合并时出现冲突,Git无法决断应该保留哪个分支的修改
a. 冲突演示
分别在 master 分支和 dev 分支修改 5.txt 文件,分别提交 commit 。最后返回 master 分支合并 git merge dev 提示冲突。
cx@DESKTOP-VS3A41J MINGW64 /g/code_workspace/git_test/git_test (master)
$ git merge dev
Auto-merging 5.txt
CONFLICT (content): Merge conflict in 5.txt
Automatic merge failed; fix conflicts and then commit the result.
此时查看 5.txt 文件
此时需要开发者决定保留哪个分支的或者都保留。删除<<< >>> === 等不需要保留的内容。
git pull = git fetch + git merge
git fetch和git pull都可以将远端仓库更新至本地那么他们之间有何区别?想要弄清楚这个问题有有几个概念不得不提。
FETCH_HEAD: 是一个版本链接,记录在本地的一个文件中,指向着目前已经从远程仓库取下来的分支的末端版本。
commit-id:在每次本地工作完成后,都会做一个git commit 操作来保存当前工作到本地的repo, 此时会产生一个commit-id,这是一个能唯一标识一个版本的序列号。 在使用git push后,这个序列号还会同步到远程仓库。
有了以上的概念再来说说git fetch
git fetch:这将更新git remote 中所有的远程仓库所包含分支的最新commit-id, 将其记录到.git/FETCH_HEAD文件中
git fetch更新远程仓库的方式如下:
git fetch origin master:tmp
//在本地新建一个temp分支,并将远程origin仓库的master分支代码下载到本地temp分支
git diff tmp
//来比较本地代码与刚刚从远程下载下来的代码的区别
git merge tmp
//合并temp分支到本地的master分支
git branch -d temp
//如果不想保留temp分支 可以用这步删除
- 如果直接使用git fetch,则步骤如下:
- 创建并更新本 地远程分支。即创建并更新origin/xxx 分支,拉取代码到origin/xxx分支上。
- 在FETCH_HEAD中设定当前分支-origin/当前分支对应,如直接到时候git merge就可以将origin/abc合并到abc分支上。
- git fetch origin
只是手动指定了要fetch的remote。在不指定分支时通常默认为master
- git fetch origin dev
指定远程remote和FETCH_HEAD,并且只拉取该分支的提交。
git pull : 首先,基于本地的FETCH_HEAD记录,比对本地的FETCH_HEAD记录与远程仓库的版本号,然后git fetch 获得当前指向的远程分支的后续版本的数据,然后再利用git merge将其与本地的当前分支合并。所以可以认为git pull是git fetch和git merge两个步骤的结合。
git pull的用法如下:
git pull <远程主机名> <远程分支名>:<本地分支名>
//取回远程主机某个分支的更新,再与本地的指定分支合并。
因此,与git pull相比git fetch相当于是从远程获取最新版本到本地,但不会自动merge。如果需要有选择的合并git fetch是更好的选择。效果相同时git pull将更为快捷。
指令
add 将文件内容添加到索引
bisect 通过二进制查找引入错误的更改
branch 列出,创建或删除分支
checkout 检查分支或路径到工作树
clone 将存储库克隆到新目录中
commit 将更改记录到存储库
diff 显示提交,提交和工作树等之间的更改
fetch 从另一个存储库下载对象和引用
grep 打印匹配图案的行
init 创建一个空的Git仓库或重新初始化一个现有的
log 显示提交日志
merge 加入两个或更多的开发历史
mv 移动或重命名文件,目录或符号链接
pull 从另一个存储库或本地分支获取并合并
push 更新远程引用以及相关对象
rebase 转发端口本地提交到更新的上游头
reset 将当前HEAD复位到指定状态
rm 从工作树和索引中删除文件
show 显示各种类型的对象
status 显示工作树状态
tag 创建,列出,删除或验证使用GPG签名的标签对象


