Git 指令

时间:2024-04-15 08:49:18

一.常见命令

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:
  1. 可直接写成 commit id,表示指定回退的版本
  2. HEAD 表示当前版本
  3. HEAD^ 上一个版本
  4. HEAD^^ 上上一个版本
  5. 以此类推...
  6. HEAD~0 表示当前版本
  7. HEAD~1上一个版本
  8. HEAD~2 上上一个版本
  9. 以次类推... 

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 创建远程仓库

创建远程仓库时,可以选择上面三个模版:

  1. Readme 文件: 介绍当前的仓库,会在仓库首页显示
  2. Issue : 当使用者发现仓库中代码的bug或者要提意见时,可以在 issue 文件中写问题是怎么引起的,重现的步骤以及报错的相关信息
  3. Pull Request 模版文件: PR是一个合并申请单,在日常开发中,我们并不可以直接在远程仓库中合并分支,需要提交一个合并申请单,由管理员审批,审批完成后,由管理员进行merge 操作

3.2 克隆远程仓库到本地

3.2.1 https 协议

git clone [https 链接]

3.2.2 SSH 协议

SSH 本质上是使用你自己电脑生成的公钥加密,私钥解密的方式来实现的.因此要想使用SSH,我们首先要生成一对非对称秘钥:

  1. 再用户主目录下(Linux默认目录),看看有没有 .ssh 目录(隐藏目录,使用 ll -a),如果有,再看看这个目录下有没有 id_rsa (私钥)和 id_rsa.pub (公钥) 这两个文件,如果没有,需要创建SSH Key:
    #此处的邮箱一定要与码云上的邮箱一致
    ssh-keygen -t rsa -C "zh5002@qq.com"
  2. 将公钥中内容拷贝,在码云个人中心上配置公钥(支持配置多个公钥)
  3. 复制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 是长连接,不需要每次输入密码)克隆,在推送时会要求每次都输入密码与用户名,解决方法:

  1. 使用缓存凭据:你可以配置 Git 使用缓存的凭据,这样它就不会在每次与远程仓库通信时询问用户名和密码:
  2. git config --global credential.helper cache

    默认情况下,Git 将在15 分钟内缓存凭据,可以通过指定一个更长的时间来调整这个设置。例如,设置缓存时间为 1 小时:

    git config --global credential.helper 'cache --timeout=3600'
  3. 使用持久性的凭据: 如果你的远程仓库支持,你可以配置 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单。