Git 的正确使用姿势与最佳实践:团队协作和版本控制的最佳实践 | 青训营

75 阅读6分钟

入门篇

基础

数据库

管理历史记录

  • 分类:
    1. 远程数据库:部署在专用服务器上,可多人共享
    2. 本地数据库:在本地机器上配置,方便个人使用
  • 创建数据库:
    1. 创建全新数据库
    2. 复制远程数据库
修改记录的提交

把文件或目录的修改记录保存到数据库

  • 系统根据修改的内容计算出没有重复的40位英文及数字来命名提交,方便未来查找

  • 建议:①不同类别的修改要分开提交;②提交时,务必输入提交信息,方便未来自己或他人理解,格式如下

    修改摘要
    空行
    修改理由
    
工作树和索引

工作树:实际操作的目录

索引:工作树和数据库之间的一层区域,只向数据库提交索引中的修改

作用:只提交选中的文件甚至是修改的某一部分,而不是整个工作树

命令
git init //在文件夹下新建数据库
git status //查看状态,会提示有哪些新建或修改的文件没有被添加到索引中
git add <file> //将文件添加到索引中,文件用空格隔开,特殊符号“.”表示当前文件夹下所有文件
git rm --cached <file> //将文件从索引中删除
git restore --staged <file> //将文件从索引中删除
git restore <file> //将文件的修改撤回
git commit -m "<message>" //提交索引中的所有修改,并附上提交信息
gitk //打开可视化git界面

共享数据库

  • push:推送
  • clone:克隆,从无到有
  • pull(=fetch+merge):本地已经有版本库,再从远程数据库中获取最新的修改并合并到本地
推送
git remote add <name> <URL> //在本地添加一个远程URL为<URL>的数据库,命名为<name>
git push [options] <repository> <branch> //向远程数据库<repository>的分支<branch>推送本地数据库,[option]可为-u,表示下次命令可省略<branch>,与第一次相同,但第一次不能省略
克隆

以Github为远程数据库

git clone [options] <URL> [<directory>] //<directory>必须是没有建立git的文件夹,如果不写则默认在当前文件夹下克隆,且新建一个以远程数据库名称命名的文件夹;如果指定文件夹,则在那个文件夹下克隆,且不会在其中新建文件夹
//[options]可选项可为-b <branch>,指定克隆某个分支,Github默认是main分支
git push //克隆下来的文件修改并且本地更新后,可以直接推送到远端,不需要加数据库和分支名称
拉取
git pull <repository> <branch>

冲突和合并

  • 当别人先push,且自己的修改地方与他一致,那么自己push的时候会发生冲突,使得推送失败
  • 解决方法:pull当前的远程数据库,会提示有冲突的文件,然后进入该文件根据提示修改,重新提交后会显示合并成功,再push就不会有冲突了

高级篇

分支(branch)

分类
  • merge分支:稳定的主线,随时可以发布release

  • topic分支:从merge分支中创建而来,创建的数量根据功能开发或bug修改任务数量而定,各自的工作完成后需要合并回merge分支,形成一个个release版本

HEAD

现在使用中的分支的最后一次更新。通常默认指向master分支的最后一次更

相对引用:

  • ~:用于指定之前某一次提交记录与HEAD的相对位置
  • ^:用于指定某一个父节点

使用HEAD指针和相对引用符号可以精确指定某一次提交(分支名指该分支的HEAD指针)

stash

用于保存还未提交(commit)的修改记录,以方便以后的应用到某一分支上

原因:在切换分支时,对于没有提交的修改记录,会自动移动到目标分支。但如果目标分支相同位置也进行了修改,checkout会失败。此时要么先提交修改记录,要么用stash暂时保存修改内容再checkout。

分支的合并
  • merge:保持原有历史记录(即有多路分叉)
  • rebase:历史记录变成一条简单的线
命令
git branch [<branchName>] //创建一个名为<branchName>的分支,如果没有该参数,则显示所有分支,其中前面带有星号*的是当前分支
git checkout <branchName> //退出当前分支,切换到<branchName>分支
git checkout -b <branchName> //创建并切换到<branchName>分支
git merge <branchName> //将<branchName>分支合并到当前分支
git branch -d <branchName> //删除分支
git rebase <branchName> //一般先要checkout到topic分支上,然后rebase到merge分支,<branchName>就是merge分支名。修改了该topic分支的历史记录,而没有改变merge分支的记录
git rebase --continue //当rebase发生冲突时,在修改了对应位置后,使用该命令提交修改信息,而不是commit
/*topic分支rebase之后,要回到merge分支,再使用merge命令进行fast-forward合并,最终merge分支的历史记录总是一条线*/

当冲突发生时,合并的方法与入门篇中的一致,手动修改冲突并提交即可。唯一区别是,基础篇中,冲突发生在同一分支中,只不过是由多人同时操作远端数据库导致的;而这里,冲突发生在不同的分支中,不论在本地还是远程数据库中

标签(tag)

  • 轻标签
  • 注解标签
git tag [<tagName>] //在HEAD指向的提交里添加名为<tagName>的标签,没有该参数时显示所有标签
git tag -a <tagName> //添加一个注解标签,具体注释在文本编辑器中编写。轻标签的注释默认为当前提交的提交信息。
git tag -am "message" <tagName> //添加注解标签,同时在命令中输入注解信息,无需打开文本编辑器进行编写
git tag -d <tagName> //删除标签

改写提交

git commit --amend //修改最近一次的提交(内容或提交信息)
git revert <HEAD> //取消某次提交,<>内使用HEAD指针。实质上是创建了一个提交,该提交取消了选中提交的修改,并没有在历史记录中删除提交
git reset --<mode> <HEAD> //将HEAD指针重置到某一位置,该位置之后的提交都被删除,索引和工作树的情况由mode决定(见下表)
git cherry-pick <提交> //从其他分支中选取某一次提交,导入当前分支。提交用40位无重复的序列号的前7位来表示
git rebase -i <HEAD> //HEAD指针指向的提交之后的所有提交都会被选中,进入一个文本编辑器,通过指令对选中的任意提交进行操作
git rebase --abort //终端正在进行的rebase
git reset --hard ORIG_HEAD //ORIG_HEAD是rebase前的HEAD指针,通过该指令可以恢复到rebase前的状态
git merge --suqash <branchName> //squash参数使<branchName>分支的所有提交汇合为一个提交,然后合并到当前分支
mode索引工作树
soft不修改不修改
mixed(默认)修改不修改
hard修改修改