JB的git之旅-git命令行

2,764 阅读18分钟

前言

关于git的介绍,这里就不在重复了,感兴趣的同学可以看下之前写的文章,有关于git跟svn区别及怎么配置git;

最近在折腾gitlab ci,想做一些工具,其中涉及到用哪些git命令,来回奔波查询,所以想写一篇git命令相关的,当做总结备忘,方便后续自己查询,同时也想加深印象;

关于工具,有很多git图形化工具,jb一开始也是使用图形化工具的,但是随着时间的流逝,在使用图形化工具遇到不少问题,
比如提交到缓冲区,不想push,怎么撤回?push后怎么回滚等等问题,对工具是有学习成本的,
与其熟悉工具,不如花点时间了解下Git命令,何况,手动敲命令,看上去很牛逼啊~

本地命令

1.配置文件-git config

一般教程在安装完git后都会引导配置用户名跟邮箱,此时就需要git config命令了,而用户名跟邮箱,都是本地git客户端的一个变量,不跟随git库而改变的~

区分configlocal
config是代表全局修改:系统中对所有用户都普遍使用的配置;对应的文件是**/etc/gitconfig**,
在使用git config --system,读取的就是这个文件
local是代表用户修改:用户目录下的配置文件,只适用于当前用户;对应的文件是**~/.gitconfig**,
在使用git config --global,读取的就是这个文件
工作目录文件是**.git/config**,这里的配置仅仅针对当前项目有效

从优先级的角度来看,local比config要高

git config user.name     #查看用户名
git config user.email    #查看邮箱
git config --global user.name "your name"    #设置用户名
git config --global user.email "your email"  #设置邮箱

#其他配置
git config --global --list   #查看全局设置相关参数列表
git config --local --list   #查看本地设置相关参数列表
git config --system --list  #查看系统设置参数列表
git config --list   #查看所有git的配置(全局+本地+系统)
git config --global core.edit 喜欢的编辑器

2.获取帮助-git help

git help  #比如,要学习config命令怎么使用,git help config

3.初始化仓库-git init

git init 仓库名 # 创建一个新的带Git仓库的项目
git init # 为已存在的项目生成一个Git仓库

4.添加文件到暂存区-git add

使用git add文件名,把文件添加到暂存区,支持批量添加

git add 文件名 # 将工作区的某个文件添加到暂存区   
git add -u # 将已跟踪文件中的修改和删除的文件添加到暂存区,不包括新增加的文件
git add -A # 将所有的已跟踪的文件的修改与删除和新增的未跟踪的文件都添加到暂存区
git add . # 将当前工作区的所有文件都加入暂存区
git add -i # 进入交互界面模式,按需添加文件到缓存区

交互模式长这样:

这里还想介绍一种场景:
假如你修改了文件 a.txt,然后把它 add 进了暂存区:

git add a.txt
git status

然后又往 a.txt 里写了几行东西。这时候你再 status 一下的话:

git status

会发现你的 a.txt 既在 "Changes to be commited" 的暂存区,又在 "Changes not staged for commit"。
不用觉得奇怪,这是因为通过 add 添加进暂存区的不是文件名,而是具体的文件改动内容。
在 add 时的改动都被添加进了暂存区,但在 add 之后的新改动并不会自动被添加进暂存区。在这时如果你提交:

git commit

那么你那些新的改动是不会被提交的。

所以需要先重新add文件,再commit,才能把最新的内容提交进去~

5.将缓存区的文件提交到本地仓库-git commit

git commit -m "提交说明" # 将暂存区内容提交到本地仓库
git commit -a -m "提交说明" # 跳过缓存区操作,直接把工作区内容提交到本地仓库
git commit -amend #合并上一次提交,在不增加一个新的commit-id的情况下将新修改的代码追加到前一次的commit-id中

如果不加-m "提交说明",git会让用你让默认编辑器(如vi)来编写提交说明,

6.查看工作区与缓冲区的状态-git status

git status # 查看工作区与暂存区的当前情况
git status -s # 让结果以更简短的形式输出

7.差异对比-git diff

git diff # 工作区与缓存区的差异
git diff 分支名 #工作区与某分支的差异,远程分支这样写:remotes/origin/分支名
git diff HEAD  # 工作区与HEAD指针指向的内容差异
git diff 提交id 文件路径 # 工作区某文件当前版本与历史版本的差异
git diff --stage # 工作区文件与上次提交的差异(1.6 版本前用 --cached)
git diff 版本TAG # 查看从某个版本后都改动内容
git diff 分支A 分支B # 比较从分支A和分支B的差异(也支持比较两个TAG)
git diff 分支A...分支B # 比较两分支在分开后各自的改动
git diff --cached  #显示所有已添加缓存区但还未提交的变更

8.查看历史提交记录-git log

git log # 查看所有commit记录(SHA-A校验和作者名称,邮箱,提交时间,提交说明)
git log -p -次数 # 查看最近多少次的提交记录
git log --stat # 显示提交日志及相关变动文件
git log --name-only # 仅显示已修改的文件清单
git log --name-status # 显示新增,修改,删除的文件清单
git log --oneline # 让提交记录以精简的一行输出
git log –graph –all --online # 图形展示分支的合并历史
git log --author=作者  # 查询作者的提交记录(和grep同时使用要加一个--all--match参数)
git log --grep=过滤信息 # 列出提交信息中包含过滤信息的提交记录
git log -S查询内容 # 和--grep类似,S和查询内容间没有空格
git log fileName # 查看某文件的修改记录

如果想定制化显示提交记录信息,也是支持的,使用-pretty进行定制:

git log --pretty=format:\"%an-%h-%s-%H\" -1

format是一个占位符,可以定制要显示的记录格式,方便后期提取分析;

以下为常用的格式占位符写法以及代表的意义:

选项 说明 选项 说明
%H 提交对象(commit)的完整哈希字串 %h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串 %t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串 %p 父对象的简短哈希字串
%an 作者(author)的名字 %ae 作者的电子邮件地址
%ad 作者修订日期(可以用 -date= 选项定制格式) %ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字 %ce 提交者的电子邮件地址
%cd 提交日期 %cr 提交日期,按多久以前的方式显示
%s 提交说明

用 oneline 或 format 时结合 --graph 选项,可以看到开头多出一些 ASCII 字符串表示的简单图形,形象地展示了每个提交所在的分支及其分化衍合情况。

以上只是简单介绍了一些 git log 命令支持的选项,下面还有一些其他常用的选项及其释义;

选项 说明
-p 按补丁格式显示每个更新之间的差异。
--word-diff 按 word diff 格式显示差异。
--stat 显示每次更新的文件修改统计信息。
--shortstat 只显示 --stat 中最后的行数修改添加移除统计。
--name-only 仅在提交信息后显示已修改的文件清单。
--name-status 显示新增、修改、删除的文件清单。
--abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。
--relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)。
--graph 显示 ASCII 图形表示的分支合并历史。
--pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。
--oneline --pretty=oneline --abbrev-commit 的简化用法。

还有一些限制输出长度的方案,比如只想看最近1天或者最新一条的日志等等;

git log --since=2.weeks  #最近两周内的提交
选项 说明
-(n) 仅显示最近的 n 条提交
--since, --after 仅显示指定时间之后的提交。
--until, --before 仅显示指定时间之前的提交。
--author 仅显示指定作者相关的提交。
--committer 仅显示指定提交者相关的提交。
–grep 仅显示含指定关键字的提交
-S 仅显示添加或移除了某个关键字的提交

详细的,可以看看git官网的介绍,点击这里~

9.查看某行代码谁提交的-get blame

git blame 文件名 # 查看某文件的每一行代码的作者,最新commit和提交时间

10.设置Git命令别名-git config –global alias

每次都要输入完整的命令,挺麻烦的,比如checkout,那有没有办法直接输入co就可以达到checkout呢?

git config --global alias.st status #此处设置st为别名,作用就是status

11.给重要的commit打标签-git tag

一般重要的提交,比如版本发布的,都需要打上一个标记,以便后续做回滚处理~
列出标签:

git tag # 在控制台打印出当前仓库的所有标签
git tag -l ‘v0.1.*’ # 搜索符合模式的标签

打标签:
git标签分为两种类型:轻量标签和附注标签
轻量标签是指向提交对象的引用,附注标签则是仓库中的一个独立对象
简单说,前者只是在提交上加个TAG,指向提交的Hash值;
后者还会保存打标签者的信息,时间和附加信息;
建议使用附注标签。

git tag 标记内容 # 轻量标签
git tag -a 标记内容 -m "附加信息" # 附加标签

创建轻量标签不需要传递参数,直接指定标签名称即可。
创建附注标签时,参数a即annotated的缩写,指定标签类型,后附标签名。
参数m指定标签说明,说明信息会保存在标签对象中。
如果想为之前的某次commit打TAG的话,可以先找出SHA1值,设置调下述命令:

git tag -a 标记内容 版本id # 比如:git tag -a v1.1 9202ff53

切换标签
与切换分支命令相同:

git checkout [tagname]

新建分支的时候也加上TAG:

git checkout -b 分支名 标记内容

用show命令查看标签对应的信息:

git show 标记内容

删除本地Tag:

git tag -d 标记内容

删除远程Tag:

git push origin --delete tag 标记内容

默认情况,git push不会把标签推送TAG到远程仓库,如果想推送到服务器,可以:

git push origin 标记内容 # 推送某标签到

# 删除所有本地仓库中不存在的TAG:
git push origin --tags 

补打标签:

git tag -a v0.1.1 9fbc3d0

12.Git命令自动补全-输命令的时候按两次tab键

13.临时存放工作目录的改动-git stash

日常生活中,总会遇到需要救火的事情,比如当你在一个分支上编码时,隔壁同学说,jb,你那个模块有BUG,赶紧修复提交下,当然,也可以commit所有文件,然后等处理完事情后再commit撤销回来,但这里要介绍的是更好用的命令-git stash;

在 Git 中,stash 指令可以帮你把工作目录的内容全部放在你本地的一个独立的地方,它不会被提交,也不会被删除,你把东西放起来之后就可以去做你的临时工作了,做完以后再来取走,就可以继续之前手头的事了。

具体说来,stash 的用法很简单。当你手头有一件临时工作要做,需要把工作目录暂时清理干净,那么你可以:

git stash

就这么简单,你的工作目录的改动就被清空了,所有改动都被存了起来。

当你忙完的时候,切回你的分支,然后:

git stash pop

之前存储的东西就都回来了。很方便吧?

注意:没有被 add 过的文件不会被 stash 起来,因为 Git 会忽略它们。如果想把这些文件也一起 stash,可以加上 -u 参数,它是 --include-untracked 的简写。就像这样:

git stash -u

文件恢复/版本回滚

1.文件恢复-已经add到暂存区,但未commit-get checkout

假如说,一个文件被add到暂存区,但是未commit,此时不小心被删除了,怎么恢复?

上面的截图是从一个新建文件到add到再到删除,可以看的出,工作区的jb.txt被删除了,但是暂存区里的jb.txt还未删除;

# 删除暂存区中的文件:
git rm 文件名

#同时删除工作区和暂存区中的文件
git rm -f 文件名

#删除暂存区的文件,不删除工作区的文件
git rm -cached 文件名

# 误删恢复文件
git checkout -- 文件名

2,撤销操作

撤销操作一般有两种情况:

  • 文件修改后还没有提交到暂存区,进行撤销操作之后,文件恢复到和版本库中一模一样

  • 文件修改后提交到了暂存区,进行撤销之后,文件恢复到在提交到暂存区之前的状态

      git checkout --文件名
    

3.

1.撤销操作-git checkout

撤销操作一般有两种情况:

  • 文件修改后还没有提交到暂存区,进行撤销操作之后,文件恢复到和版本库中一模一样
  • 文件修改后提交到了暂存区,进行撤销之后,文件恢复到在提交到暂存区之前的状态

文件未提交到暂存区

git checkout --文件名

文件提交到了暂存区,但未提交到本地仓库
如果某个文件写错了,想要修改,但是已经add到了暂存区,那需要先撤销到工作区

git reset HEAD 文件名

此时文件已经撤销到工作区,但是文件内容是没变化,如果想要恢复到修改之前的状态,就要使用:

git checkout -- 文件名

2.删除文件-git rm

# 删除暂存区中的文件:
git rm 文件名
    
#同时删除工作区和暂存区中的文件
git rm -f 文件名
    
#删除暂存区的文件,不删除工作区的文件
git rm -cached 文件名

3.恢复文件-git reset

如果想要将某个文件恢复到某个版本时的状态,可以使用以下的命令:

git checkout id 文件名

id就是使用git log时的commit id,取前7位即可~

如果要将所有我呢见都恢复到某个版本,可以用下面的命令:

git checkout id 文件名

除了用id恢复到某个版本库时的状态,还有别的写法:

//恢复到上一个版本
git reset --hard HEAD^ 
// 恢复到前两个版本
git reset --hard HEAD~2   或者  git reset --hard HEAD^^
# git log查看到的commit值,取前七位即可
git reset --hard 版本号 

4.查看输入指令记录-git reflog

git reflog 可以查看所有分支的所有操作记录(包括commit和reset的操作),包括已经被删除的commit记录,git log则不能察看已经删除了的commit记录,

5.撤销某次提交-git revert

有时可能想撤销某次提交所做的更改,可以使用revert命令

git revert HEAD # 撤销最近的一个提交
git revert 版本号 # 撤销某次commit

特别注意,这里的撤销不是真的撤销,而且生成一个新的提交覆盖旧的提交,而提交的内容是之前的内容而已,所以,提交记录还是会存在的,别侥幸哦~

6.查看某次提交修改内存-git slow

git show 提交id # 查看某次commit的修改内容

7.查看某个分支的版本号-git rev-parse

git rev-parse 分支名 # 查看分支commit的版本号,可以写HEAD

8.找回文件象-git fsck

git fsck --lost-found  #可以查到丢失的记录

本地分支

1.分支创建与切换-git branch

git branch 分支名 # 创建分支
git branch # 查看本地分支

git checkout 分支名 # 切换分支
git checkout -b 分支名 # 创建分支同时切换到这个分支

2.合并分支-git merge

git merge <name> #合并某分支到当前分支

3.冲突处理

当在提交一个文件或者merge的时候,如果也有对应修改的地方,就会出现冲突,与svn不同的是,git就算冲突,内容也是被合并的,此时就需要处理冲突文件;

打开文件后会发现,代码中会被<<<<<<< 、=======、>>>>>>>包围,这是冲突标记:
冲突标记<<<<<<< 与=======之间的内容是我的修改,=======与>>>>>>>之间的内容是别人的修改。

那就要处理,最后记得把符号都干掉即可~

4.取消merge

当在处理冲突的时候,突然不想merge了,怎么办?可以用git merge --abort手动取消~

git merge --abort

输入这行代码,Git 仓库就会回到 merge 前的状态

5.删除分支

git branch -d 分支名 # 删除分支,分支上有未提交更改是不能删除的
git branch -D 分支名 # 强行删除分支,尽管这个分支上有未提交的更改

这里说明下,不能直接删除当前所在的分支,如果要删除当前所在的分支,必须要先checkout到别的分支,再删除之前的分支~

6.恢复误删分支

git log --branches="被删除的分支名" # 找到被删分支最新的commitb版本号
git branch 分支名 版本号(前七位即可) # 恢复被删分支

7.分支重命名

git branch -m 老分支名 新分支名 # 分支重命名

远程仓库与远程分支

1.推送本地仓库到远程仓库-git push

    git remote add origin 远程仓库地址  #关联本地与远程仓库
    
    git push -u origin master  
    #将本地仓库推送到远程仓库,-u是首次提交需要,后续都不需要
    git remote set-url origin 远程仓库地址 #修改远程仓库地址
    
    # 也可以先删除origin后再添加
    git remote rm origin    # 删除仓库关联
    git remote add origin 远程仓库地址 # 添加仓库关联

2.克隆远程仓库-git clone

git clone 仓库地址 # 克隆项目到当前文件夹下
git clone 仓库地址 目录名 # 克隆项目到特定目录下

3.同步远程仓库更新-git pull

git pull #在当前分支直接输入git pull即可

4.查看远程分支

git branch -r # 查看所有分支

5.拉取远程分支到本地仓库

git checkout -b 本地分支 远程分支 # 会在本地新建分支,并自动切换到该分支
git fetch origin 远程分支:本地分支 # 会在本地新建分支,但不会自动切换,还需checkout
git branch --set-upstream 本地分支 远程分支 # 建立本地分支与远程分支的链接

6.删除远程分支

git push origin :分支名 

关于命令行,大致就介绍到这里吧,详细点的信息,就请移步到git官方查询文吧:
git-scm.com/book/zh/v2

项目迁移

日常工作中,可能会出现项目迁移的情况,简单说就是把gitlab项目迁移到其他仓库那;

这里先假设,原gitlab地址:git.jbold.com,新gitlab地址:git.jbnew.com

迁移步骤

  1. 查看目前旧仓库的gitlab地址

     $ git remote -v
     origin  git.jbold.com:jb/jbtest.git (fetch)
     origin  git.jbold.com:jb/jbtest.git (push)
    
  2. 在新gitlab上新建new项目,生成gitlab地址:

     git@git.jbnew.com/jb/jbtest-new.git
    
  3. 设置本地gitlab地址替换成新的gitlab地址

     jb@LAPTOP-2R0431R1 MINGW64 ~/gitprojects/jbtest (master)
     $ git remote set-url origin git@git.jbnew.com/jb/jbtest-new.git
     
     jb@LAPTOP-2R0431R1 MINGW64 ~/gitprojects/jbtest (master)
     $ git remote -v
     origin  git@git.jbnew.com/jb/jbtest-new.git (fetch)
     origin  git@git.jbnew.com/jb/jbtest-new.git (push)
    
  4. 查看分支情况

      $ git branch -a
     * master
       remotes/origin/HEAD -> origin/master
       remotes/origin/master
     这里只有一个master,因此直接推送master
    
  5. 把本地指定分支,推送到集团远程代码仓库

     $ git push origin master:master
    

就这样,代码就从旧的仓库地址迁移到新的仓库地址了

小结

本文主要介绍了常见的git命令,覆盖到文件操作,本地分支以及远程分支相关的操作;
感触最深的就是git log的定制化功能,真的对于提取内容很方便~

谢谢大家~