Git使用指南
一、环境配置
//配置提交代码时的用户信息
$ git config --global user.name "test"
$ git config --global user.email "test@163.com"
说明:git config 级别有三类:
- 仓库级别 --local 【优先级最高】, 配置文件是当前仓库下的.git/config
- 用户级别 --global【优先级次之】, 配置文件是用户宿主目录下的~/.gitconfig
- 系统级别 --system【优先级最低】, 配置文件是git安装目录下的 /etc/gitconfig
// 查询配置信息
$ git config --global --list
二、获取Git仓库
-
初始化本地仓库(git init)
$ git init git-demo //git init在项目的根目录下创建一个 .git 的子目录,用来保存当前项目的一些版本信息 $ cd git-demo $ echo "Git学习" > README.md $ git add README.md $ git commit -m 'init repo and add README.md' $ git log
初始化后,会在当前目录(git-demo)自动创建 .git 文件夹,git相关文件以及版本都将保存在该文件夹中。
./git 目录说明:
- config:包含项目特有的配置选项(分支等)
- HEAD:指向当前被检出的分支
- COMMIT_EDITMSG:上次提交或准备提交的 commit msg 记录
- index:保存暂存区信息
- hooks目录:客户端或服务端的钩子脚本。
- info目录:全局性排除,那些需要排除但是不希望记录在 .gitignore 文件中的排除文件记录在这个目录下的exclude 文件中
- object目录:存储所有的数据内容
- refs目录:存储指向数据(分支、远程仓库和标签)的提交对象指针
**注意:**git 的 gc 会将 git refs 中的文件整合保存到 .git/packed-fefs 中,保证git 执行效率分支快速检出。如果更新了引用,git 不会更新 packed-fefs 文件,只会在 ./git/refs/heads 下加一条数据。所以引用的寻找都是先找 ./git/refs/heads 下的数据,当 ./git/refs/heads 下找不到数据,再去 .git/packed-fefs 中找 - packed-refs:记录分支当前在哪个 commit 节点上
基本概念:
**origin:默认远程版本库名
**master:默认分支名
**origin/master:远程默认分支名
**HEAD:当前分支顶端Commit的别名,即当前分支最近的一个提交的SHA-1哈希值
**ORIG_HEAD:上次HEAD指针的位置。注:当执行git reset/git pull/git merge命令时,git会把老的HEAD拷贝到文件.git/ORIG_HEAD中,在后续命令中可以使用ORIG_HEAD引用这个提交
****commit(提交)**:每个commit都是全部文件的完整快照,并用一个 commit-id(基于文件的内容或目录结构计算出来的40位十六进制的SHA-1哈希值)来唯一标志。从某个角度上来说,Git维护的就是一个个commit-id有向无环图。
**detached HEAD:HEAD没有指向任何分支的状态。一般有以下几种情况会出现这种情况:
① 使用checkout命令跳到某个没有分支指着的commit时
② reaset处理冲突时所处的状态
③ 切换到某个远程分支cache上时
$ git remote add origin git@github.com:test/git-demo.git
$ git push origin master
说明:remote可以理解为是远端代码托管平台的地址,git借助remote可以添加、删除远程存储库和管理各种远程分支等。
remote管理:
查看当前仓库的 remote
$ git remote -v
添加remote,本地关联远程仓库
$ git remote add <shortname> <url>
删除remote
$ git remote rm <shortname>
远程克隆(git clone)
$ git clone git@github.com:test/git-demo.git
三、Git工作流程
一般工作流程:
-
在工作目录中添加,修改文件;
-
将需要进行版本管理的文件放入暂存区域;
-
将暂存区域的文件提交到本地仓库;
-
将本地仓库更新推送到远程仓库。
图示说明: -
远程仓库(远端代码托管仓库):
//将远程仓库代码拉取到本地仓库 $ git pull #抓取远程仓库最新数据同时自动进行合并(merge) #等同于下面命令 $git fetch #不会自动合并数据【抓取到本地,但没有合并到工作区,在隐藏库的object中以二进制存放】 $git merge origin/master #手动合并:将远程仓库最新数据合并到工作区 //将远程仓库代码直接复制到本地仓库 $ git clone #不仅仅是文件,历史和日志信息会一起下载下来
-
本地仓库(本地代码仓库):
//将本地仓库代码推送到远程仓库 $ git push
本地仓库有 Git 维护的三棵“树”组成,这是 Git 的核心框架,分别是:工作区、暂存区和 Git 版本库。
工作区:就是你在电脑里能看到的目录,即存放项目代码的地方。
//将变动添加到暂存区 $ git add 文件名 或者 git add . #将工作区的某个文件、某些文件、或者是所有文件,所作出的修改(新建、删除也算的),添加至暂存区,此时文件就可以被git commit
暂存区:英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中,用于临时存放你的改动,保存即将提交的文件列表信息。
//将暂存区的变动正式提交到本地仓库 $ git commit -m '提交说明'
版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库,保存着提交的所有版本的数据,其中,HEAD 指向最近一次放入仓库的版本。
快速上手Git
拉取远程仓库代码
$ git clone 仓库地址
查看本地仓库当前状态,如:哪些文件被修改过、那些文件还未提交到版本库等
$ git status
Git标示出README.md为“Untracked files”(未追踪的文件)
追踪文件,添加到暂存区
$ git add
//然后使用git status查看状态
README.md状态变成了“Changes to be committed”,说明README.md在暂存区生成了快照,等待被提交。
“git rm --cached README.md”----可以将文件状态还原为未暂存状态(Untracked files)。
修改README.md文件,保存。
$ git status
“Changes not staged for commit”状态,表明文件已经修改,但是还没有放入暂存区,也就是没生成快照。此时commit,只能将修改之前的文件快照提交到本地仓库
**注:**只有暂存区域的文件(即:文件状态为“Changes to be committed”)才会被提交。
“git add README.md”----将已修改文件更新到暂存区域中;
“git checkout – README.txt”----撤销修改;
"git restore " —把文件从暂存区撤销,回到未被追踪的状态,在工作区是不会其作用的。
小结:Git在未进行commit操作之前,存在三种状态:
**Untracked files:**未跟踪的状态,这是文件的初始状态
**Changes not staged for commit:**文件在暂存区中生成了快照等待被提交(commit)
**Changes to be committed:**文件生成过快照,但是又有了新的修改,并且没有生成新的快照
每种状态之间可以随意进行互相转换
文件提交
$ git commit -m "<这里写commit的描述>"
//git commit只负责把暂存区的修改提交
//提交的备注写错了,可以用以下命令修改刚刚提交的备注
$ git commit --amend
//:w:保存文本
//:q:退出编辑模式
//:wq:保存并退出
查看提交记录,即:历史版本记录
$ git log
$ git log --pretty=oneline 查看单行日志
$ git log --graph 以分支合并图方式查看日志
//对比本地文件和本地仓库中文件的区别
$ git diff <文件名>
将远程仓库上的最新代码拉取到本地仓库
$ git pull
#在拉去远程仓库代码时如出现冲突,需要通过编辑解决冲突,然后执行git add, git commit命令
本地仓库的修改提交到远程仓库
$ git push
#用本地仓库的commit记录去覆盖远程仓库的commit记录
#git push不加参数只能上传到从远程仓库clone或者pull下来的分支,如需push在本地创建的分支则需使用git push origin <branch-name>
四、分支管理
分支用来管理开发的,mster代表主分支,最终的代码都整合到这里面去。多人协作开发时,可以创建特性分支,待所有特性分支开发完成,整合到master分支。
-
建立新分支
1.首先查看当前分支
// 列出本地分支 $ git branch #-a代表查看本地和远程的分支 #-r列出所有仓库分支
当前只有master分支,* master 标识当前处于master分支。
2.新建分支
$ git checkout -b dev
#-b代表同时切换到dev分支下面去
此时已经有了两个分支,且当前位于dev分之下。
$ git checkout [branch-name] //切换分支
-
整合分支
当我们在dev下开发完成后,需要整合到master分支时:
1.切换本地分支到master
$ git checkout master
2.将远程仓库的最新代码pull下来
$ git pull origin master
3.然后再把本地的dev代码整合到master
$ git merge dev #git merge -m "fix: 同步dev分支信息" dev
注:在遇到一个分支上有多个 commit,但由于某些原因,只想提交部分commit,merge 到 master 分支,使用git cherry-pick commitId,commitId需要获取在合并分支dev下获取,然后checkout到当前分支master执行git-cherry-pick。可以同时cherry-pick多个commitId,但是需要按提交的先后顺序排列,不然可能出现异常,如新增的文件找不到等。
一般的,git不能cherry-pick一个合并提交,此时可能处于(master|CHERRY-PICKING)状态,使用git cherry-pick --skip可以跳出 (master|CHERRY-PICKING)状态。
4.dev分支的代码已经在master分支的本地仓库,执行push,更新到远程仓库的master
$ git push origin master
-
删除分支
//删除本地分支,不会删除远程分支 $ git branch -d [branch-name] // 删除远程分支 $ git branch origin -d [branch-name]
五、标签管理
标签:用来记录开发过程中的关键时刻, 例如发布版本、 有重大修改等,标签也是版本库的一个快照,标签不能移动。
1、创建标签
$ git tag <tag-name>
$ git tag #查看所有标签
默认标签是打在最新提交的commit上的。如果需要对过去的提交版本打标签,通过找到历史提交的commit_id。
$ git log --pretty=oneline --abbrev-commit
$ git tag <tag-name> <commit_id>
$git show <tag-name> #查看标签信息
可以创建带有说明的标签,用-a指定标签名,-m指定说明文字 git tag -a -m “描述说明” <commit_id>
删除标签
$ git tag -d <tag-name>
推送标签至远程
$ git push origin <tag-name> #推送某个标签到远程
$git push origin --tags #一次性推送全部尚未推送到远程仓库的本地标签
删除远程标签
先从本地删除,然后再从远程删除
$ git tag -d <tag-name>
$ git push origin :refs/tags/<tag-name>
重命名tag
先删除,后添加
$ git tag -d <old-tag>
$ git tag -a <new-tag> -m"information"
获取指定tag代码
第一步:切换到指定标签,提示你当前处于一个“detached HEAD" 状态,因为 tag 相当于是一个快照,是不能更改它的代码的
$ git checkout <tag-name>
第二步:如果要在 tag 代码的基础上做修改,你需要一个分支
$ git checkout -b branch_name tag_name
第三步:切回到之前的HEAD指向(以master为例)
$ git checkout master
六、版本回滚
Git版本回滚,即回滚commit,在push代码到远程仓库过程中,不免会遇到各种问题,可能涉及回滚代码。
1、在工作区的代码
$ git checkout -- a.txt # 丢弃某个文件,或者
$ git checkout -- . # 丢弃全部
**注意:**git checkout –- . 丢弃全部,包括:新增的文件会被删除、删除的文件会恢复回来、修改的文件会回去,回到暂存区之前的样子。
2、代码git add到暂存区,并未commit提交
$ git reset HEAD . 或者
$ git reset HEAD a.txt
这个命令仅改变暂存区,并不改变工作区,这意味着在无任何其他操作的情况下,工作区中的实际文件同该命令运行之前无任何变化。
3、git commit到本地分支、但没有git push到远程仓库
$ git log # 得到你需要回退的commit_id
$ git reset --hard <commit_id> # 回到其中你想要的某个版
或者
$ git reset --hard HEAD^ # 回到最新的一次提交
或者
$ git reset HEAD^ #此时代码保留,回到 git add 之前
4、修改提交已经git push到远程仓库
1)通过git reset直接删除指定的commit。
$ git log #获取需要回退的commit_id
$ git reset --hard <commit_id>
$ git push origin HEAD --force # 强制提交一次,之前错误的提交就从远程仓库删除
2)通过git revert用一次新的commit来回滚之前的commit
$ git log # 获取需要回退的commit_id
$ git revert <commit_id> #撤销指定的版本,撤销也会作为一次提交进行保存