一.常见命令
1.1 初始化仓库
#初始化仓库
git init
#查看隐藏文件
ll -a
#查看隐藏文件.git结构
tree .git/
1.2 创建/删除用户信息
#创建用户信息
git config user.email "151859@163.com"
git config user.name "zsl"
#查看
git config -l
#删除用户信息
git config --unset user.name
git config --unset user.email
#创建全局用户信息
git config --global user.name "zsl"
git config --global user.email "123@163.com"
删除全局用户信息
git config --global --unset user.name
git config --global --unset user.email
1.3 工作区、暂存区、版本库
- 工作区: 在电脑上我们要写代码或文件的目录
- 暂存区: 英文名叫stage或index. 一般存放在 .git 目录下的index文件(.git/index)中,我们把暂存区有时也叫作索引
- 版本库:又名仓库,英文名 repository。工作区有一个.git ,它不算工作区,而是Git 的版本仓库。这个版本库里面的所有文件都可以被Git 管理起来,每个文件的修改、删除,Git 都能跟踪,以便任何时刻都可以追踪历史,或者在将来的某个时刻可以“还原”。
- 图中左侧为工作区,右侧为版本库,Git 的版本库里存了需多的东西,其中最重要的就是缓存区。
- 在创建Git 版本库时,Git 会为我们自动创建一个唯一的master 分支,以及指向master 的一个指针叫 HEAD。
- 当工作区修改(或新增)的文件执行 git add 命令时,暂存区目录树的文件索引会被更新。
- 当执行提交操作 git commit 时,master 分支会做相应的更新,可以简单理解为暂存区的目录树才会被真正的写道版本库中。
- 修改的工作区的内容会写入对象库的一个新的 git 对象中,每个对象中都有一个唯一id,暂存区和master中的树里的文件索引中存储的就是这个唯一id,通过id在objects 中找到对应的版本.
由上述描述我们便能得知:通过新建或粘贴进目录的文件,并不能称之为向仓库中新增文件,而只是在工作区新增了文件。必须要通过使用 git add 和 git commit 命令才能将文件添加到仓库中进行管理
添加至暂存区 git add:
#添加一个或多个文件,在add后加具体文件名
git add [file2] [file2]
#添加指定目录到缓存区
git add [dir]
#添加当前目录中的所有文件
git add .
git commit操作:
#提交暂存区全部内容到本地仓库中
git commit -m "description"
#提交暂存区的指定文件到仓库区中
git commit [file1] [file2] -m "description"
注意 git commit 后面的 -m 选项,要跟上描述本次提交的信息,有用户自己完成,这部分内容绝对不能省略,并要好好描述,是用来记录你提交的细节
查看git 中文件内容:
#-p 是因为文件前两位是目录名
git cat-file -p 94852815cdf81ac7ba38613493891db1341ffb0e
1.4 master 中各文件内容及含义
最初文件目录:
在file1 file2 file3 文件中修改commit过后:
在HEAD 文件中保存着储存master头指针位置的文件所在目录,查看master文件中的内容,里面存储的是master分支的头结点文件id。打开该文件后,里面存储的分别是:
- tree ... : “ ... ” 中存储的是当前版本中所有的文件id
- parent ...:“ ... ” 中存储的是上个一个版本头指针的文件id(里面内容结构和当前结构相同,首次commit 的头节点除外,其中没有parent)
- author ...:创建本仓库的作者
- committer ...:提交本次仓库的作者
1.5 其他命令
1.5.1 git status
查看当前状态
1.5.2 git diff
查看工作区和暂存区的区别:
git diff readme
1.5.3 版本回退 - git reset
相关命令:
#查看日志,日志中记录了每次commit 后头指针的id
git log --pretty=oneline
#-graph 以图的方式打印; --abbrev-commit id 压缩打印
git log --graph --abbrev-commit
#查看commit 和 git reset 日志
git reflog
#只回退工作区内容:--必须要加,否者就是另外一个命令
git checkout -- readme
如果想要回退到原来的莫个版本或者回退之前的版本,可以通过上述两个命令来找到对应的版本id,然后通过reset 进行回退。
语法格式:
git reset [--soft | --mixed | --hard] [HEAD]
- --soft:参数对于工作区和暂存区的内容都不变,只是将版本库的内容都回退为指定版本
- --mixed:默认选项,使用时可以不用使用该参数。该参数将暂存区和版本库的内容都回退到指定版本内容,工作区文件不变
- --hard:参数将暂存区、工作区以及版本库都回退到指定版本。切记工作区由未提交的代码时不要用这个命令,因为工作区会回滚,你没有提交的代码就在也找不回了,所以使用该参数一定要慎重。
- HEAD:
- 可直接写成 commit id,表示指定回退的版本
- HEAD 表示当前版本
- HEAD^ 上一个版本
- HEAD^^ 上上一个版本
- 以此类推...
- HEAD~0 表示当前版本
- HEAD~1上一个版本
- HEAD~2 上上一个版本
- 以次类推...
1.6 删除版本库中文件
#三步操作
rm file1
git add.
git commit
#两步操作
git rm file1
git commit
1.7 配置命令别名
#将 git status -> git st
git config --global alias.st status
#log --pretty=oneline --abbrev-commit -> lpa
git config --global alias.lpa 'log --pretty=oneline --abbrev-commit'
二. 分支管理
2.1 分支的创建、切换、合并与删除
#查看当前所有分支
git branch
#创建分支
git branch [分支名]
#创建并切换分支
git checkout -b [分支名]
#切换分支
git checkout [分支名]
#合并分支
git merge [分支名}
#删除分支,若删除某个分支,不能再该分支上进行删除,必须切换到其他分支
git branch -d [分支名]
#分支中由未commit 的数据,强制删除
git branch -D [分支名]
当我们创建分支时,分支和master指向同一版本对象,在commit之前,工作区无论怎么修改,两个分支中文件的内容都是一样的。
但是,当有一条分支commit之后,此时两个分支中工作区的文件内容就不一样了。
2.2 合并冲突
#创建并切换到新的分支
git checkout -b [分支名]
分支和master 进行合并时,当master 中的内容和分支上一次合并或者创建时的内容不一致时,就会发生合并冲突
<<<<<<<< HEAD
......
=======
......
>>>>>>>> dev1
当发生冲突时,vim 发生冲突的文件时,可以看到以上情况:
“<<<<<< HEAD” ~ “=====” 之间的内容和 “=====~>>> dev1”之间的内容就是发生冲突的内容,我们可以选择保留的内容,将不需要的进行删除(正常的vim 删除操作),删除完后再进行 add、commit 和 merge 操作。
合并后,分支的指向和master指向并不是同一个版本:
从上图可以看出,当我们解决冲突后,需要重新 add 和 commit ,因此master 指向了新commit 的版本,而分支指向的仍是合并之前的版本
2.3 合并模式
通常合并分支时,当master 分支内容没有新的变动(commit过或者合并过其他分支),就会采用 Fastforward 模式。在这种模式下,删除分支后,产看分支历史时,会丢掉分支信息,看不出来最新提交到底是merge 进来的还是正常提交(commit)的。
但在合并冲突时,我们需要先解决冲突,再进行一次新的提交 ,得到的最终状态为:
那这种就不是Fast forward 模式了,这样的好处是,从分支历史上就可以看出分支信息。例如我们现在已经删除了再合并部分创建的dev 分支,但是依旧能看到master 其实是由其他分支合并得到的 :
指令:
git merge dev --no-ff -m "merge with master by no-ff"
--no-ff 参数,表示禁用Fast forward 模式。禁用Fast forward 模式后合并会创建一个新的 commit(合并过后dev分支和master的头指针指向不同的版本id),所以要加上 -m 参数,把描述写进去
2.4 bug 分支
假如我们在 dev2 分支上进行开发,开发到一半,突然发现master 分支上面有bug,需要去删除。在Git 中,每个bug 都可以通过给一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
但是,现在 dev2 分支的代码在工作区中开发了一半,但是还无法提交,而master 分支和dev2 又指向同一个版本文件,怎么办?
此时Git 提供了 git stash 命令,可以将当前的工作信息进行储藏,被存储的内容可以在将来的某个时间恢复出来
#将工作区修改的内容放到存储区当中,以栈的方式存放元素
git stash
#stash当中若有多个版本,pop的顺序和栈类似,遵循先进后出,pop后内容会删除
git stash pop
#可以查看stash当中提交的不同版本
git stash list
#恢复指定的stash,但是恢复后,stash内容并不删除,
git stash apply stash@{0}
#删除指定stash
git stash drop [stash@{0}]
注意:文件必须是commit过,被git管理的文件,否则无法 stash
合并某个stash版本,本质上和分支合并差不多,也会有合并冲突,因此当我们合并过一个之后,在我们合并第二个时需要先提交此次合并的内容,并且下次合并时可能会发生合并冲突
当我们创建bug 分支并修改完后,就可以与master 分支合并,但是由于master 版本更新过,所以当我们要合并 dev2分支时,就会发生合并冲突。由于合并冲突是需要我们手动解决,解决冲突可能会出错,导致master 代码出错。因此我们可以现在dev2 分支上进行合并,解决完合并冲突后,再转换到master 分支上,合并dev 分支。
三 . git 远程操作
3.1 创建远程仓库
创建远程仓库时,可以选择上面三个模版:
- Readme 文件: 介绍当前的仓库,会在仓库首页显示
- Issue : 当使用者发现仓库中代码的bug或者要提意见时,可以在 issue 文件中写问题是怎么引起的,重现的步骤以及报错的相关信息
- Pull Request 模版文件: PR是一个合并申请单,在日常开发中,我们并不可以直接在远程仓库中合并分支,需要提交一个合并申请单,由管理员审批,审批完成后,由管理员进行merge 操作
3.2 克隆远程仓库到本地
3.2.1 https 协议
git clone [https 链接]
3.2.2 SSH 协议
SSH 本质上是使用你自己电脑生成的公钥加密,私钥解密的方式来实现的.因此要想使用SSH,我们首先要生成一对非对称秘钥:
- 再用户主目录下(Linux默认目录),看看有没有 .ssh 目录(隐藏目录,使用 ll -a),如果有,再看看这个目录下有没有 id_rsa (私钥)和 id_rsa.pub (公钥) 这两个文件,如果没有,需要创建SSH Key:
#此处的邮箱一定要与码云上的邮箱一致 ssh-keygen -t rsa -C "zh5002@qq.com"
- 将公钥中内容拷贝,在码云个人中心上配置公钥(支持配置多个公钥)
- 复制SSH 链接,克隆到本地
git clone [SSH链接]
3.3 向远程仓库推送
git push origin master:master
- origin:是一个远程仓库的别名。在git 中,origin 是默认的远程仓库的名称,它通常指向最初克隆的仓库。当你使用 git clone 克隆一个远程仓库时,git 会自动将该远程仓库命名为 origin ,你可以将其他远程仓库添加到你的本地仓库,并为它们设置不同的别名
- master:master:这个语法是指定本地分支和远程分支的映射关系。在这种情况下,master:master 意味着将本地的 master 分支推送到远程仓库的 master 分支。这种格式为<local_branch_name>:<remote_branch_name>,它告诉 Git 推送哪个本地分支到远程仓库的哪个分支
使用 https (SSH 是长连接,不需要每次输入密码)克隆,在推送时会要求每次都输入密码与用户名,解决方法:
- 使用缓存凭据:你可以配置 Git 使用缓存的凭据,这样它就不会在每次与远程仓库通信时询问用户名和密码:
git config --global credential.helper cache
默认情况下,Git 将在15 分钟内缓存凭据,可以通过指定一个更长的时间来调整这个设置。例如,设置缓存时间为 1 小时:
git config --global credential.helper 'cache --timeout=3600'
使用持久性的凭据: 如果你的远程仓库支持,你可以配置 Git 使用持久性凭据存储(例如 macOS Keychain 或 Windows Credential Manager)来存储用户名和密码。
#macOS git config --global credential.helper osxkeychain #windows git config --global credential.helper manager
3.4 拉取远程仓库内容
git pull origin master:master
此处的 origin 是远程仓库的名称, 第一个master 是远程分支,第二个 master 是本地master 分支。将远程 origin 仓库中的 master 分支拉下来合并到本地的master 分支
3.5 忽略特殊文件
在 Git 工作区的根目录下创建一个特殊的 .gitignore文件,然后把要忽略的文件名填进去,Git 就会自动忽略这些文件。
#忽略所有以.jar 和 .war 结尾的文件
*.jar
*.war
#排除 java.war 文件
!java.war
#强制添加某个文件
git add -f java.jar
3.6 标签管理
#给当前版本打标签
git tag v1.0
#给指定版本:eff6d31 打标签
git tag v2.0 eff6d31 -m '发布标签版本2.0'
#查看 v2.0 标签详细信息
git show v2.0
#删除 v1.0 标签
git tag -d v1.0
#将标签推送至远程仓库
git push origin v1.0
#将所有标签推送至远程仓库
git pust origin --tags
#将本地标签删除并推送到远程仓库
git tag -d v1.0
git push origin :v1.0
四. 多人协作开发
在公司中,一个项目往往是要由多个人来协作完成单的。此时就涉及到了多人协作开发
目标:master 分支下 file.txt 文件新增代码 "aaa" 、"bbb"
实现:开发者1 新增"aaa",开发者2新增"bbb"
条件:在一个分支下协作完成
常用命令
#查看远程分支
git branch -r
#查看所有分支
git branch -a
#创建一个dev分支并与远程仓库dev分支连接(创建连接之后就可以直接使用git push/pull 短命令推送和拉取)
git branch dev origin/dev
#查看本地分支与远程分支连接关系
git branch -vv
#将本地dev2 分支与远程dev 分支创建连接
git branch --set-upstream-to=origin/dev dev2
#删除本地远程仓库已经删除的分支
git remote prune origin
在提交pr 之前,为了避免合并冲突,先在分支上合并master分支,再提交pr单。