Git操作备忘录

191 阅读13分钟

git相关概念

Repository

一个仓库(Repository)可以理解为管理一个项目的文件夹,只不过里面有一些配置文件,这些配置文件用于对项目进行版本控制。

git和github的关系

github是项目的托管平台,只支持git作为唯一的版本库格式进行托管。

要注意git和github并不是密不可分,可以理解为git是一个软件,用于管理项目仓库;

而github是在git的基础上建立的。

github只能使用git,但是git可以应用于其他支持git的项目托管平台,比如gitee。

git bash与cmd

git bash封装了cmd,并在此基础上加了bash环境的环境变量。

但是在封装的过程中,windows可能对调用自己cmd命令行控件的第三方应用设了限制,因此git bash在绝大多数情况下可以像普通cmd一样使用。

git clone与下载zip的区别

下载zip会默认下载master主版本工程文件,下载后的文件夹为name-master,而git clone不会有。

使用git clone下载时会现在本地初始化git项目文件,这也是比直接下载zip文件多出的一个.git文件夹。

就是通过这个多出的.git文件夹可以修改源码后重新往github提交,而直接下载zip的工程文件没办法提交了。

所以如果直接使用从github上下载的东西而不push上去的话,两种方法都可以。

git的三个工作区域

工作目录、暂存区、本地仓库、远程的git仓库

工作区(workspace) :平时存放代码的地方

暂存区(index/stage) :临时存放改动,事实上只是一个文件。

本地仓库(repository) :最终确定的文件保存到仓库,成为一个新的版本,并且对他人可见。

远程仓库(remote) :代码托管的远程服务器

image.png

git基本操作

git的配置文件

查看系统配置git config --system --list

查看用户配置git config --global --list

查看本仓库配置git config --local --list

系统配置文件所在位置[安装位置]/etc/gitconfig

用户配置文件所在位置C:/Users/[xxx]/.gitconfig

向仓库中添加更新

添加文件到暂存区git add .

提交暂存区内容到本地仓库git commit -m "[提交描述]"

配置用户名邮箱

配置用户名git config --global user.name "[用户名]"

配置邮箱git config --global user.email "[邮箱]"

注意这里的用户名和邮箱只是起到一个区分身份的作用,可以随便填写。

配置免密登录

本地生成rsa密钥对ssh-keygen -t rsa -C "[邮箱]"

-C是comment的缩写

-C表示提供一个注释,用于识别这个密钥。因为邮箱地址具有唯一性所以一般用来识别密钥

查看生成的公钥cat ~/.ssh/id_rsa.pub,在github添加SSH公钥

测试是否添加成功git remote -v,如果没报错,说明添加成功。

刚配置好时没有内容,可以手动添加默认的或者自定义的远程链接的别名,也可以等第一次push到github的时候git将仓库链接自动添加到origin别名里。

添加远程关联git remote add 关联名 https://仓库链接

查看远程关联信息git remote -v

删除远程关联git remote rm 关联名

push到githubgit push 关联名 当前本地分支名

拉取仓库修改并提交

在github上创建一个仓库之后,就可以用git clone url将这个仓库完整的拉取下来。

然后进入此项目目录中进行修改,修改完后要同步到github上,就要进行下面的操作。

先将本地的修改同步到暂存区git add .

然后将暂存区的更新同步到本地仓库git commit -m "注释描述"

最后将本地仓库push到github上,git push或者git push 关联名 本地当前分支名:要推送到远程的分支名(可以是新的)

git add时报错warning: LF will be replaced by CRLF in解决办法

windows中的换行符为 CRLF, 而在linux下的换行符为LF,git为了解决跨平台开发的换行问题,提供了自动换行转换,这个功能是默认处于”自动模式“即开启状态的。这样在git add的时候即便没有修改内容,由于转换换行的原因,git也会认为你修改过内容,所以会提示warning。不需要关注

版本回退

查看版本历史记录git reflog,更详细的信息用git log

可以使用git reset --hard commitId来切换项目的版本。注意--hard的作用是同时作用于工作区和暂存区。

reset回退方式可以将代码库中的某个版本回退到之前的某个版本,会更改本地分支的历史记录,不建议使用。

revert命令可以创建一个新的提交,撤销特定提交引入的更改,但保留提交历史。git revert commitId

即reset是回到某个commtId,revert是撤销某个commitId

git切换版本的原理,底层其实是移动HEAD指针。

可以看本地的.git目录下的HEAD文件,可以看到里面指针指向refs/heads/master,说明当前是在master分支上。然后查看指针指向的文件,里面保存的就是当前的commitId。

同分支commitId切换

HEAD是一个指针,通常情况下,它指向当前所在分支,而分支又指向一个commit提交。

HEAD并不总指向一个分支,某些时候仅指向某个commit提交(git checkout commitId的时候),这就形成detached HEAD。切换到 detached HEAD 状态时,会有一个警告

也就是说切换到某个commit后,只能查看代码历史,不能对代码进行修改、提交等操作。

解决方法是在切换的时候直接创建一个新的分支,git switch -c [新分支名],可以想象一个分支图来理解

git的分支

查看分支git branch -v, git branch -a

创建分支git branch 分支名

切换分支git checkout 分支名

合并分支git merge 分支名,注意如果要将一个分支合并到主分支上,需要先checkout到主分支上,再进行merge。

切换分支本质上也是修改的HEAD指针。

fetch和pull区别

image.png

git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。git fetch用户从远程仓库获取最新的更改,但是不会合并到自己的当前工作分支

git pull则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决。因此最好只使用git fetch而不使用git pull

fork\clone\fetch\push\pr全流程

pull request是对于开源项目来说,自己没有权限直接操作远程仓库。可以fork一个项目,然后更改,通过pull request的方式提交给仓库所有者。

几点说明:

1.git clone时会把整个仓库clone下来,也就是说仓库有多少分支就都会clone下来,然后可以用git chekcout <分支名>来切换到想要操作的分支上。

2.修改的是哪个分支(也就是说当前是在哪个分支),fetch的时候就要fetch哪个分支。

3.在PR的时候一定要看清楚要把当前分支PR到原repo的哪个分支上去,千万别a分支PR到b分支上去。

1.使用gitee,账号azsxdc0账号下创建myrepo仓库

2.chen账号fork这个仓库,并clone下来

3.chen账号修改user.name和user.email

git config --local user.name "xx"
git config --local user.email "xx@qq.com"

4.chen账号修改readme.md内容如下

1.hello~1

然后还需要git add ., git commit -m "..."来做一个节点

5.这时再从azsxdc0账号下重新clone一份,修改user.name和user.email

6.azsxdc0账号修改readme.md内容如下

2.hello~2

7.azsxdc0账号commit并push到主分支(这里用来模拟chen账号开发完之后想要push时,原仓库azdxdc0账号的源码已经更新了的情况)

8.chen账号这个时候需要fetch一下azdxdc0账号的新源码,操作如下

9.先添加remote

git remote add upstream https://gitee.com/azsxdc0/myrepo.git

10.把azsxdc0账号新源码fetch下来

git fetch upstream master
语法:git fetch <remote添加的原仓库名> <master分支>

这个时候会将azsxdc0账号master新版本下载下来

image.png

11.将remotes/upstream/master合并到本地master分支,因为两个readme.md文件内容不一样,因此报错conflict

注意这里的一个做法是不切换到远程master分支,而是以本地master分支为基础,让远程master来合并到本地master分支

image.png

12.使用git status查看冲突信息,发现readme.md都修改了

image.png

13.这个时候再去看readme.md,可以看到冲突

image.png

14.适当修改后,再次

git add .
git commit -m "fix conflict"
git merge remotes/upstream/master
git push

15.chen账号上gitee页面上提交pull request

16.azsxdc0账号上审核一下pull request就可以了

17.chen账号接下来的开发就正常进行,还是在提交之前先fetch一下

git fetch用法

用法1和用法2的区别就是在fetch之后的checkout不同,用法1是切换到远程分支,用法2是切换到本地分支,推荐使用用法2切换到本地分支

git fetch用法1(不推荐)

应用场景为多个人一个项目,

在clone一个项目后,进行一定的修改,比如加了一个文件,然后git commit,主要切换分支之前一定要git commit,否则当前工作为丢失。

要跟其他项目合并,先执行git fetch,执行git checkout -b 本地分支-dev origin/远程分支拉取远程分支

注意这里的操作是以远程分支为基础新创建一个本地的分支

这时就将远程的这个分支拉下来,然后执行merge,将刚才修改的内容merge到本地分支-dev中,git merge main

git log可以查看到相应的日志

将合并后的分支推送到远程原有分支git push origin 本地分支-dev:远程分支

具体fetch的原理图参考https://blog.csdn.net/qq_42780289/article/details/98049574

git fetch用法2(推荐)

应用场景为一个人一个项目,在两台电脑上操作,相当于坚果云的备份

本地创建两个文件夹用于模拟两个电脑,gitee上创建项目test2,

在1文件夹中clone下来,新建a.txt,然后commit和push

在2文件夹下,clone下来test2项目,新建b.txt,然后commit和push,git push origin master:v1.0此时push到v1.0分支

回到1文件夹下,git fetch,git checkout v1.0注意这里是切换到本地的v1.0分支而不是git checkout origin/v1.0

继续在1文件夹下,新建c.txt,然后commit,push到v2.0分支git push origin v1.0:v2.0

再回到2文件夹下,git fetch,git checkout v2.0,新建d.txt,然后commit,git push origin v2.0:v3.0

checkout时遇到的问题

对于新创建的文件(没有commit),不论是git checkout 分支还是git reset等都不会影响,

只能通过git checkout .; git clean -df清除

如果当前分支已经修改一些内容,现在要checkout到其他分支,那么会有以下几种操作

  • 1.直接把当前修改(没有commit)清除了不要了,强制恢复到上一个commit

    • git checkout .  //放弃本地修改,新增和删除的仍然没有恢复
      git clean -df       //从工作目录中移除没有track的文件
      git log, git reset --hard <commit_id>
      git checkout <分支名>
      
    • 另外需要注意,如果git reset到前两个版本(中间跳过一个版本)时,前一个版本增加的文件不会被删除,而是会以untracked的状态留下来,这时如果不想要前一个版本留下来的文件,就又回到了清除当前修改的操作,需要执行git checkout, git clean -df, ...操作
  • 2.这个版本还要

    • 2.1(推荐)先把当前修改commit一下,git add ., git commit -m "", git checkout <分支名>

    • 2.2或者,暂存修改

      git stash   暂存修改
      git stash list 显示所有stash数据
      git stash apply 恢复最近一次的暂存修改
      git stash apply stash@{1} 恢复索引号对应的暂存
      git stash drop stash@{1} 删除索引号对应的暂存
      git stash pop 将最近一次暂存pop出来并删除
      

PR注意事项

pull requests时注意要选择合并后不删除原分支,或者删除原分支后在本地立刻git push一下,要不然自己仓库的分支就没了

Issue事务

Issue用于跟踪待办事项、bug、功能需求等。

Issue在项目中可以承担用户反馈的作用,用户可以在这个地方提出bug反馈与优化建议,也可以为开发者服务,用于记录待完成的任务。

一般来说,可以包含以下类型:

  • 软件的bug
  • 功能优化建议
  • 待完成的任务

milestone里程碑

里程碑是一个项目计划管理工具,用于集中管理 Issue 和 Pull Request 进度。每个里程碑milestone中可以选择issue中优先级高的问题和新功能

里程碑的操作也在issue中

一个里程碑可以包含多个issue

Issue相关操作

当然除了下面commit提交时更新Issue,还可以直接在web页面上点击对应图标进行修改

Gitee 新的方案已经不采用 issue 的 id 标识 issue,而是使用 ident

比如编号为I99H9Vissue_identissue_urlhttps://gitee.com/chenfight/test1/issues/I99H9V

一个 commit message 可同时关联多个任务,不同 issue_ident 之间请用空格隔开

通过commit关联事务

关键字:link, linked, linking, relate, related, relating

形式:commit message中输入link #issue_ident或者 link issue_url

通过commit关闭事务

关键字:close, closes, closing, closed, fixed, fix, resolved

形式:commit message中输入close #issue_identclose issue_url

通过commit评论事务

关键字:comment, reply

形式:commit message中输入comment #issue_identcomment issue_url

管理多个证书

参考连接https://blog.csdn.net/qq_35658349/article/details/103334343

git commit

commit message语法参考https://blog.csdn.net/xtho62/article/details/108196796

具体操作

在项目根目录创建.gitmessage文件

# head: <type>(<scope>): <subject>
# - type: ✨ feat, 🐞 fix, 📃 docs, 🌈 style, 🦄 refactor, 🎈 perf, 🧪 test, 🔧 build, 🐎 ci, 🐳 chore, ↩ revert
# - scope: can be empty (eg. if the change is a global or difficult to assign to a single component)
# - subject: start with verb (such as 'change'), 50-character line
#

# body: 72-character wrapped. This should answer:
# * Why was this change necessary?
# * How does it address the problem?
# * Are there any side effects?
#

# footer: 
# - Include a link to the ticket, if any.
# - BREAKING CHANGE
#

通过 git config 命令指定 commit.template 的路径

git config commit.template .gitmessage

然后在提交的的时候不加-m

git commit

这时就会出现模板文件,按照上面的规则编写commit,此时还可以在footer位置加fix等操作把issue关掉

最后git push即可