介绍
- 工作区:就是你在电脑里能看到的目录。
- 暂存区:英文叫stage, 或index。一般存放在 “.git目录下” 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
- 版本库:工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
关系介绍
下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系:
图中左侧为工作区,右侧为版本库。在版本库中标记为 "index"
的区域是暂存区(stage, index),标记为 “master” 的是 master分支所代表的目录树。
HEAD指针: 每个git仓库有且仅有一个HEAD指针,它通常指向当前某个活动的本地分支指针(最初本地仓库master)。也可以是某个提交记录、某个tag,但这会让其处于 detached HEAD(游离头)状态,此状态下的所有提交都无效。
图中我们可以看出此时 "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 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
GIT介绍
GIT是由C语言开发的分布式版本控制系统。
分布式vs集中式
分布式版本控制系统
- 无需网络就可以进行所有版本控制操作
- 追踪并管理的是元数据
- 每个工作成员的机器都有完整的版本库
集中式版本控制系统
- 使用必须连接网络
- 追踪并管理的是文件
- 只有一个中央版本库
基本常用命令
第一次使用git的时候,需要设置用户信息和用户邮箱,用于辨识提交者身份。
1 | git config --global user.name <git用户名> |
基本操作
1 | git init # 把当前的目录变成可以用git进行版本控制的git仓库,生成隐藏.git文件。 |
“commit message”内容尽量规范!
当某一次提交后,突然想起漏提交了文件,或不小心提交了不满意的代码时,可以使用git commit --amend -m "message"
指令。它可以在不增加一个新的commit-id的情况下将新修改的代码追加到前一次的commit-id中。提交之后message也将被本次的message覆盖,所以还需要再次添加上次的message。
push
1 | git push origin name |
把当前master分支推送到远程库;
-u
表示记住分支和地址,下次使用git push
即可。
remote
1 | git remote add origin reposityUrl # 关联一个远程库 |
clone
1 | git clone reposityUrl # 从远程库中克隆 |
pull
1 | git pull |
从远程仓库拉下来到本地库然后合并相当于
git fetch
+git merge
。
一般push前先拉去最新版本,避免代码冲突,如果有冲突需要解决了冲突才能提交。
fetch
1 | git fetch # 从远程库抓下最新版本,但是不合并 |
fetch是从远程库到本地库,但是未在工作区,需要
git merge
merge
1 | git merge dev # 在当前的分支上合并dev分支 |
分支合并也是在本地完成,新的分支只有在合并后才允许被删除。
如果分支合并是出现冲突需要解决了冲突才能合并,使用git status
查看冲突文件。
branch/checkout
1 | git branch # 查看当前所有的分支,前面有"*"的为目前所在的分支。 |
git checkout -- file
相当于取消对文档的修改,将最新的本地版本库的本文件复制覆盖它。(比较危险!)
reflog,log
1 | git log # 显示所有提交过的版本信息:commit id,提交者,日期(完成后按Q键退出) |
想看到自己的操作记录,则可以使用log与reflog,它两个的区别如下:
git log
命令可以显示所有提交过的版本信息;
如果感觉太繁琐,可以加上参数--pretty=oneline
,只会显示版本号和提交时的备注信息。git reflog
可以查看所有分支的所有操作记录。(包括已经被删除的commit记录和reset的操作)
reset
1 | git reset --hard HEAD^ |
版本回退的操作一般是先查看历史提交版本的commit id,使用git reflog
接着使用命令git reset --hard commit_id
回退版本
最后 git push -f (origin master可写可不写)
提交远程库
版本退回是从本地仓库到暂存区,如果已经提交远程库,此时的版本是低于最新的版本的会拒绝提交,
所以需要用git push -f origin master
强制提交。
status
1 | git status |
查看你的文件在暂存区和工作目录的状态,默认是较为详细的显示,并提示你可以用何种命令完成你接下来可能要做的事情。
1 | git status -s |
较为简单的输出当前的状态,如:
1 | $ git status -s |
你可以看到,在简短输出中,有两栏。第一栏是暂存区的,第二栏则是工作目录的。这里表示:
README.md
在暂存区中的状态是modify
hello.rd
在工作目录中的状态是delete
world.java
还未添加到版本控制。
diff
1 | git diff XX # 查看XX文件修改了哪些内容 |
rm, mv
1 | git rm # 将文件从暂存区和工作目录删除,-f 为强制删除 |
git rm
用来删除文件、目录。git mv
命令用于移动或重命名一个文件、目录。
比如删除photos文件,本地删除后,远程仓库还会有,所以执行如下操作:
1 | git rm -r photos |
submodule
添加子模组
1 | git submodule add url # 添加子模组 |
修改、删除子模组
1 | 如果远程库子模组有更新, 你要更新本地库子模组应该在git pull之后运行 |
当一个远程库有子模组时,直接clone子模组只是一个空文件夹,需要进入子模组的空文件夹init
和update
才行。
或者使用递归克隆git clone --recursive 远程库
子模组更新后,父模组必须更新,因为需要更新commit id。
tag
基本命令
1 | git tag -a v1.0 # 给最新一次提交打标签 |
我们可以用特定的搜索模式列出符合条件的标签。在 Git 自身项目仓库中,有着超过 240 个标签,如果你只对 1.4.2 系列的版本感兴趣,可以运行下面的命令:
1 | git tag -l 'v1.4.2.*' |
当你执行git tag -a
命令时,Git会打开你的编辑器,让你写一句标签注解,就像你给提交写注解一样。
如果我们忘了给某个提交打标签,又将它发布了,我们可以给它追加标签。
例如,假设我们发布了提交85fc7e7(最后一行),但是那时候忘了给它打标签。 我们现在也可以:
1 | $ git tag -a v0.9 85fc7e7 |
同步远程-本地Tag
1 | git tag | xargs git tag -d |
推送标签
默认情况下,git push 并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。其命令格式如同推送分支,运行 git push origin [tagname] 即可:如果要一次推送所有本地新增的标签上去,可以使用 –tags 选项:然后,其他人克隆共享仓库或拉取数据同步后,也会看到这些标签。
stash
1 | git stash # 把当前的工作隐藏起来,等以后恢复现场后继续工作。 |
gitk
1 | gitk # git自带GUI |
其他
- Gearn Git Branching
(
提示A:在克隆远程库曾出现问题
没有弹出输入框验证框,直接就提示认证失败。
解决办法:使用Git输入下面两条命令(需要管理员权限)
1 | git credential-manager uninstall # 清除缓存账号密码(卸载) |
提示B:在提交上传远程库曾出现问题
git push提交到远程仓库时,git会卡住等半天都没反应,只能按Ctrl+C退出。
解决办法:使用Git输入以下面的命令
1 | git config --global sendpack.sideband false # 配置文件添加属性 |
输入下面的命令可以查看仓库配置,看到sendpack.sideband等于false就可以重新push了
1 | git config --local -l # 查看配置信息 |
)
托管网站
托管网站解释
- 一个组织可以有 0-N 个用户,一个用户默认为一个组织,可以加入多个组织。一个组织有 0-N 个仓库,一个仓库中有 0-N 个代码文件。
- 工单可以反馈问题情况等,里程碑是开发者建立(要在某个时间之前完成什么功能)。
- 提交(Commit)可以与工单关联,工单(Issue)可以与里程碑关联。
- 版本发布是发布重要的版本
- 百科是开发者编写关于这个项目的一些内容
- 动态可以看到仓库的变动信息
- fork 相当于克隆仓库 后续不会改变。镜像仓库可以随父仓库更新,主要用于国外网站,创建一个国内的镜像来加快响应速度。
托管网站/平台 issue 相关常见标签
bug
描述的问题是一个 bugenhancement
功能增强,没有 feature 也可以指 New feature or request。feature
新功能duplicate
问题重复invalid
可用的,不是 bug。question
疑问,需要进一步的信息。wontfix
不会修复此问题help-wanted
需要帮助good first issue
Good for newcomers
托管网站/平台 issue 相关内部流程-理想化
- 收到产品需求后建立 issue
- 管理员评估 issue 并分配标签,指派负责人。
- 负责人检查已指派的 issue,选择项目发布 tag 以及建立里程碑(Milestone)。
- 负责人开发并推送代码,commit 信息开头或末尾附带 issue 编号,比如:
Feat: [#1] 提交代码信息
/Feat: 提交代码信息 [#1]
。 - 也可以后续对接其他平台,使用托管网站 api 即可。
- 这样就可以通过一个平台了解工作进度与开发发布任务
License
规则
Git 开发规则
- Master 的 BUG 必须最少且趋近于零,为最稳定的版本。
- 每次 Commit 讯息应该具体确实填写,不可模稜两可、不可出现版本号,eg: 修复BUG、增加功能。
- 禁止 Commit IDE 的 project data
- 禁止上传垃圾程序码
分支 (Branch)
- 命名规则:应以此分支主要目的命名 (修复BUG、新增某特定功能)
- 不可出现版本号、模块ID。
- 合并后的分支应删除
- 禁止删除历史版本、造成Branch断裂。
- 禁止将已发生的冲突上传到 Git 。
推荐使用SourceTree提高协作开发效率,可以建立一套开发体系,规范团队协作,规范开发、测试流程,也可以使用GitFlow工作流与HotFix等。
- Gitee 教程
- 参考文章