Git 学习笔记

简书本身不支持生成目录,自己通过pandoc生成的目录在简书也变成了新页面打开。心好累,推荐大家用这个简书文章左侧目录, 以下是插件效果:

image.png

廖雪峰老师Git教程真的很不错,花了大概两三个小时过了一遍,受益良多,以记之。
本文不再介绍 Git 的安装配置过程和基本的 linux 命令操作。

初始化仓库

  • 首先建一个目录 learngit ,在终端进入到该目录下
  • 然后通过git init命令把这个目录变成Git可以管理的仓库
$ git init  #初始化仓库

把文件添加到版本库

创建一个 readme.txt,放在 learngit 目录下(或者子目录)

$ vim readme.txt
Vim 快捷键说明
Esc 退出编辑,跳到命令模式
:w 保存文件但不退出 vim
:w! 强制保存,不退出 vim
:wq 保存文件并退出 vim
:q 不保存文件,退出 vim
:q! 不保存文件,强制退出 vim
:e! 放弃所有修改,从上次保存文件开始再编辑

1.把文件添加到暂存区

使用git add file_name

$ git add readme.txt

一次添加多个文件

$ git add *.txt

一次添加所有文件

$ git add --all
or
$ git add .

git add --allgit add . 都可以把「所有改动(增删改)」添加到暂存区,区别是 git add .只会添加当前 目录(包括子目录)下的所有改动,git add --all在任何目录下操作都可以添加当前 工作区 的所有改动。

2.把文件提交到版本库

$ git commit -m "wrote a readme file" 

-m "wrote a readme file"是说明本次 commit 你做了什么事情,简要描述清楚即可(重点是描述清楚,中、英文不限)。

git commit 指定文件的时候会直接提交 工作区 的文件,不指定文件的时候提交的是缓存区stage的所有文件

$ git commit readme.txt -m "commit message"

查看Git安装目录

$ where git # Windows
$ which git # Mac

时光穿梭机

版本退回

git reset --hard commit_id    # 该操作会在`git reflog`中生成记录
  • Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
    • Git的commit_d(版本号)是一个十六进制的用SHA1计算出来的数字
    • 在Git中用HEAD表示当前版本,前一个版本就是HEAD^,前一百个版本写成HEAD~100
    • 使用git reset --hard HEAD^命令退回上一个版本
  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本
    • 使用git log --pretty=oneline让记录单行显示
    • 使用git loggit reflogfile_name查看指定文件的历史
  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本
    • Git 提供一个命令git reflog来记录你的每一次命令,这样就可以找到所有版本的commit id

工作区和暂存区

  • 工作区(Working Directory)
    你在电脑里能看到的目录
  • 版本库(Repository)
    工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库.我们可以称它为Repo
    Repo里存放了很多东西,其中最重要的就是暂存区stage(或者叫index),还有Git为我们自动创建的第一个分支(Branch)master.以及指向master的一个指针叫HEAD.
    repo.png

前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。

掌握仓库当前的状态

$ git status

查看修改内容

下面是关于 git diff的一些使用区别
[图片上传失败...(image-c72280-1547095525316)]
另外可以使用git diff commit_id_1 commit_id_2比较两个不同版本的区别

撤销修改

  • 场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file_name
    • 可以用git checkout -- *丢弃所有工作区文件的修改
  • 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步
    • 第一步用命令git reset HEAD file_name就回到了场景1
      • 使用git reset HEAD丢弃所有暂存区的修改
    • 第二步按场景1操作
  • 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,git reset --hard HEAD,不过前提是没有推送到远程库。

注意:使用版本退回操作git reset --hard会导致所有暂存区和工作区的当前修改但未 commit 的内容全部丢弃.。

文件名里有空格和()的情况

Git命令(或者所有的shell命令中)中出现括“()”时系统把它看做一个有特殊意义的命令从而尝试去执行它。
因此如果文件名中出现括号,系统找不到括号里要执行的命令就会报错。
我们要让系统忽略括号的特殊意义,方法是用“”双引号把文件名括起来,或者用转义符将括号转义.
例如文件名为git (1).md
以下的写法都是可以的:
git add "git (1).md"
git add git" "\(1\).md
git add git" (1)".md

删除文件

使用rm file_name删除本地文件
使用git add file_name==git rm file_name提交删除到暂存区
使用git commit -m "commit msg"提交到本地库
注意: 可以直接使用git rm file_name删除本地文件以及提交删除到暂存区,但仅用于暂存区有此本地文件的情况

远程仓库

注册GitHub账号

由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:

  • 第1步:创建SSH Key
$ ssh-keygen -t rsa -C  "youremail@example.com"

然后在用户主目录里找到.ssh目录,里面有id_rsaid_rsa.pub两个文件id_rsa是私钥,id_rsa.pub是公钥.

cd ~进入用户主目录
cd .ssh进入.ssh目录
ls列出.ssh目录的文件
cat ~/.ssh/id_rsa.pub看到id_rsa.pub文件的内容

  • 第2步:登陆GitHub

打开“Account settings”,“SSH Keys”页面:然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容

添加远程库

  • 要关联一个远程库,使用命令
git remote add origin git@server_name:path/repo_name.git

这里使用的命令是
git remote add origin git@github.com:HuChanghong/learngit.git

  • 关联后,使用命令git push -u origin master第一次推送master分支的所有内容

  • 此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改

ssh不行是因为你没有设置ssh秘钥
1:生成秘钥:ssh-keygen -t rsa -C "你自己的邮箱"
(这里不要设置密码,直接按回车就可以,以后更新就不需要密码)
2:id_rsa 这个文件是你的私钥、id_rsa.pub是你的公共密钥,用记事本打开文件id_rsa.pub,把里面的内容复制到github配置ssh
3:添加私秘钥到ssh: ssh-add id_rsa(如果添加失败可以先执行命令ssh-agent bash,然后再次添加私秘钥。)
4: 用ssh -T git@github.com 判断是否绑定成功。如果返回successfully 表示成功

从远程库克隆

  • 要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。
git clone git@github.com:username/reponame.git
  • Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。

取消远程链接

  • 查看本地库关联了那些远程库git remote -v
  • 取消本地目录下关联的远程库git remote rm origin
    • 此处origin是指你创建与远程库的链接的时候所使用的名字

分支管理

创建与合并分支

  • 查看分支:git branch
  • 创建分支:git branch <name>
  • 切换分支:git checkout <name>
  • 创建+切换分支:git checkout -b <name>
  • 合并某分支到当前分支:git merge <name>
  • 删除分支:git branch -d <name>

解决冲突

  • 当Git无法自动合并分支时,就必须首先解决冲突。
  • 解决冲突后,再提交,合并完成。
  • 解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
  • 用git log --graph命令可以看到分支合并图。

git merge branch_name提示 conflict
git status查看冲突的文件
打开这个文件,修改保存
用带参数的git log也可以看到分支的合并情况:
git log --graph --pretty=oneline --abbrev-commit
最后删除不需要的分支

分支管理策略

在实际开发中,我们应该按照几个基本原则进行分支管理:首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

注意--no-ff参数,表示禁用Fast forward
因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去

git merge --no-ff -m "balabala" branch_name

Bug分支

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。

Git提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作

git stash

我理解的stash,就像是把当前的WIP压栈(这里WIP的含义就是所有修改了但未commit的数据)然后再一个一个取出来,默认的git stash pop是按照自栈顶开始的顺序依次出栈,也可以使用git stash pop stash@{num}的方式取出指定的WIP
我们可以用git stash list查看当前压栈了多少个WIP

注意:git stash不能将未被追踪的文件(untracked file)压栈,也就是从未被git add过的文件,也就是你在使用git status命令看到的提示Untracked files所列出的文件,所以在git stash之前一定要用git status确认没有Untracked files
另外在有WIP没有commit 或者stash的情况下是无法切换分支的

Feature分支

  • 开发一个新feature,最好新建一个分支;
  • 如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除

多人协作

多人协作的工作模式通常是这样:

  • 首先,可以试图用git push origin <branch-name>推送自己的修改;
  • 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
  • 如果合并有冲突,则解决冲突,并在本地提交;
  • 没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!
  • 如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to=origin/<branch-name> <branch-name>
  • 这就是多人协作的工作模式,一旦熟悉了,就非常简单。
  • 查看远程库信息,使用git remote -v
  • 本地新建的分支如果不推送到远程,对其他人就是不可见的;
  • 从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
  • 在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
  • 建立本地分支和远程分支的关联,使用git branch --set-upstream-to=origin/branch-name branch-name
  • 从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。

rebase

这是git文档强调的使用注意情形和原则

只对尚未推送或分享给别人的本地修改执行rebase操作清理历史;
从不对已推送至别处的提交执行rebase操作

下图来自这篇链接

git_merge.png

git_rebase.png

git rebase会把你的my work分支里的每个提交commit取消掉,并且把它们临时 保存为补丁patch(这些补丁放到".git/rebase"目录中),然后把mywork分支更新 到最新的origin分支,最后把保存的这些补丁应用到mywork分支上。

mywork分支更新之后,它会指向这些新创建的提交commit,而那些老的提交会被丢弃。 如果运行垃圾收集命令pruning garbage collection, 这些被丢弃的提交就会删除.

标签管理

发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。

类似IP和域名的关系

创建标签

  • 命令git tag <tagname>用于新建一个标签,默认为HEAD,也可以指定一个commit id
    • git tag tag_name commit_id
  • 命令git tag -a <tagname> -m "blablabla..."可以指定标签信息;
    • -a指定标签名,-m指定说明文字
  • 命令git tag可以查看所有标签。
    • git show tag_name查看标签信息

操作标签

命令git push origin <tagname>可以推送一个本地标签;
命令git push origin --tags可以推送全部未推送过的本地标签;
命令git tag -d <tagname>可以删除一个本地标签;
命令git push origin :refs/tags/<tagname>可以删除一个远程标签。

关联多个远程库

使用多个远程库时,我们要注意,git给远程库起的默认名称是origin,如果有多个远程库,我们需要用不同的名称来标识不同的远程库。

先用git remote -v查看远程库信息

如果本地库已经关联了origin的远程库,并且,该远程库指向GitHub。我们可以删除已有的GitHub远程库

git remote rm origin

使用如下命令关联远程库

git remote add remote_name git@server_name:path/repo_name.git

例如要关联Github远程库

git remote add github git@github.com:Github_id/repo_name.git

再比如要关联码云远程库

git remote add gitee git@gitee.com:Github_id/repo_name.git

此时要推送到不同的远程库则代码中使用对应的远程库名称(remote_name)

git push remote_name master

自定义Git

忽略特殊文件

有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,每次git status都会显示Untracked files ...,有强迫症的童鞋心里肯定不爽。好在Git考虑到了大家的感受,这个问题解决起来也很简单,在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。不需要从头写.gitignore文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore

忽略文件的原则是:

  1. 忽略操作系统自动生成的文件,比如缩略图等;
  2. 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
  3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

可以用git add -f强制添加被gitignore的文件
可以用git check-ignore命令检查是什么规则导致的无法添加文件

git check-ignore -v file_name

注意:.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理!

配置别名

  st = status
  co = checkout
  br = branch
  cm = commit
  unstage = reset HEAD
  last = log -1
  lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
每个仓库的Git配置文件都放在.git/config文件,打开配置文件,别名就在[alias]后面,要删除别名,直接把对应的行删掉即可
当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig

查看用户的配置信息使用git config --global --list命令
查看当前仓库的配置信息使用git config --local --list命令

删除别名

命令删除一个已定义的别名 git config --global --unset alias.ci
cd .git vim config打开对应的配置文件,别名就在[alias]后面,直接把对应的行删掉即可

gitconfig配置文件的读取顺序:
linux中类似用户的配置文件一样有3层,系统级,用户级,项目级。
windows也基本一样,但常常只存在于是用户根目录(C:\User\xxx),项目目录中。 最下层的覆盖上面的,alias配置也在其中,手动改配置文件也和命令一样。 加了--global选项的,表示配置写到了用户级,--system是系统级,win是在安装目录(如C:\Program Files\Git\mingw64\etc),不加就在项目级

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容