git learn

这是一篇拖了很久的 Blog,偶然间翻到,发现正好可以用来梳理一些忘记了的点。欢迎拍砖。

一、git 删除文件及恢复

1)git rm <file>

做了两件事:

1.删除文件;

2.将被删除的文件纳入到暂存区(stage、index)

【补充】git 的三个区域:工作区、暂存区、仓库

若想恢复被删除的文件,需进行两个操作:

1.git reset HEAD <filename> ,将待删除的文件从暂存区恢复到工作区

2.git checkout -- <filename>,将工作区中的修改丢弃掉

2)rm file

做了一件事,将 file 删除,这时,被删除掉的文件并未纳入暂存区中 ,还在工作区中

所以要恢复的话,直接丢弃工作区的操作就行:git checkout -- file

有个需要注意的就是 Changes to be committed: 表示文件被放在了暂存区

Changes not staged for commit表示文件还在工作区

二、git log 的一些操作

1.commit 信息错误,想修正?

——git commit --amend -m '再次修正' : 就可以把最近的一条 log 中的消息修改为 ‘再次修正’

2.显示最近的 n 条日志

—— git log -n

3.定制 log 显示格式

——git log --prettt=oneline : 单行显示

——git log --pretty=format:"%h - %an, % ar:%s" :不同参数有不同格式

三、.gitignore 与分支

1.首先我们需要知道一个开发习惯:项目本身的 ide 的项目管理文件是不应该提交到版本控制中的。(比如 .idea 这种)因为项目管理文件中往往标识了项目引用的路径,或者是 IDE 用来识别项目等信息,不同人之间合作时,这些信息是不同的,不应该被 pull。

jar 包是不允许也不应该丢到版本控制中的,应该放的是 build.gradle/pom.xml 这样的描述文件

然而,我们的修改总会导致工作区不干净,同时又不能 git add . 全部添加,这种情况该如何处理?——此时,.gitignore 就发挥它的作用了

假设我们的项目管理文件叫 setting.properties ,那么我们应该如此操作:

vi .gitignore
## 然后在 .gitignore 中写 setting.properties ,保存退出
git add .gitignore
git commit -m "添加了.gitignore"

注:.gitignore 支持通配符、正则表达式整来通配文件名

2.忽略文件的写法

一个 * 表示一层目录,** 表示所有层次

*.a  # 忽略所有 .a 结尾的文件

!lib.a #  lib.a 除外

/TODO # 忽略根目录下的 TODO 文件,不包括子目录下的TODO
	
build/  #忽略 build/ 下的所有文件

doc/*.txt #忽略 doc/下一级目录的所有 .txt ,但是下下级别不管

/**/a.txt. # 忽略所有的 a.txt 文件

3.分支

SVN 的分支是重量级的,会复制一份完整的分支信息,而 git 分支是轻量级的,仅仅创建了一个指针

a.查看当前分支: git branch, * 所在的分支表示当前分支

b.创建新分支: git branch new _branch

c.切换分支:git checkout new_branch ,刚刚切换到新分支的一刹那,两个分支的内容是相同的。后续的开发则是独立的

d.切换到前一个分支:git checkout - 。 ‘-’ 表示前一个,cd - 也会切换到之前的目录

四、分支重要操作

1.删除分支: git branch -d new_branch -d 表示 delete

不能删除当前正在使用的分支;不能删除有文件改动而且未合并的分支

git branch -D new_branch :强制删除 new_branch (不推荐)

2.创建并切换到新分支

git branch new _branch + git checkout new_branch <=> git checkout -b new_branch

3.当前在 matser 上,希望将 new_branch 上的修改合并到 master 上

git merge new_branch 会输出 Fast-forwad(FF,快进)。现在就可以 -d 删除 new_branch 了

即:将 git merge 后跟的分支,合并到当前所在的分支上

PS:Fast-forwad:快进,指的是没有任何冲突,直接移动指针的操作

4.查看当前分支上最近一条的提交消息: git branch -v

所以,什么是分支呢?

——其实,分支是一个 commit 对象链

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yabLpmYP-1592959258243)(E:\goodgoodstudy\课外书\git learn.assets\git4-1 分支.png)]

而 HEAD 和 master 其实也是两个指针:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gs2CKuqT-1592959258258)(E:\goodgoodstudy\课外书\git learn.assets\git4-2 head master.png)]

如上图, master 指向第三次提交,HEAD 指向当前所在的分支。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1K2Vvy45-1592959258263)(E:\goodgoodstudy\课外书\git learn.assets\git4-3 dev.png)]

而这个图,相当于创建了 master 和 dev 分支,当前处在 dev 分支上。

所以 HEAD 保存在哪里呢?

cd .git
ls
cat HEAD  # 会随着切换不同分支而改变

5.冲突:如果不同分支修改的是同个文件,则合并时就会发生冲突,需要手动解决;如果修改的不是同个文件,直接合并即可

1)如果 dev 分支和 master 分支都对 test.txt 修改了一行,此时在 master 分支上尝试合并,会报错:

Auto-merging text.txt
CONFLICT (content):Merge confict in test.txt
Automatic merge failed:fix conflicts and commit the result.

即,自动合并失败,产生了冲突,需要修复冲突后重新提交。

此时,text.txt 的内容会成为标准的冲突形式:

xxxxx(没冲突的)
<<<<<< HEAD
hello cloei
======
hello swift
>>>>>> dev

#即:
#发生冲突的内容在当前分支是 <<< HEAD 和 ==== 之间的,
#另外的分支的冲突是 ==== 和 >>>> dev 的
#此时直接编辑即可,保留想保留的就行

修改完之后的 status 是:You have unmerged paths ,有未合并的文件;

git add text.txt 来标识 “冲突解决了”,此时的 status 是 “冲突解决了,但是还处于 merge 状态”;

使用 git commit 来 conclude merge (结束冲突),此时的工作环境才是 clean 的。

2)如果再切换回 dev 上进行合并,此时不会再冲突了(因为已经被解决了)

仅仅发生快进(FF)动作,而且对应的文件内容变成了冲突合并后的文件内容

3)git -am “add a new line” <=> git add . + git commit -m "add a new line"

6.分支改名

git branch -m master master2 :将 master 分支改名为 master2

五、分支进阶与版本回退

1.快进 fast-forwad ff

  • 如果可能,合并分支时 git 会使用 ff 模式

  • 在这种模式下,删除分支时会丢掉分支信息

  • 可加上 --no-ff 来禁用,会多出一个 commit id:git merge --no-ff dev

    • 此时的 merge 需要再输入 commit message ,同时会保留下分支信息
  • 用图形化方式查看 log : git log --graph

2.版本回退

用 git 来作为版本控制工具,任何时候都有后悔药可吃。

  • git reset -- hard HEAD^ : 回退几个版本,就有几个 ^
  • git reset -- hard HEAD~2 : 回退到相对于当前版本前的第 2 个版本
  • git reset -- hard commit_id :直接指明回到该 id 的版本

3.如果回到了前面的版本,又想回到后面的版本呢?

由于git log 仅仅记录当前版本及其以前的日志,无法看到后面的 commit_id ,所以 git log 失效了。需要使用 git reflog ,它记录下了操作日志,记录下了所有的操作信息,包括 commit_id

所以正确的方式是:

git reflog   # 找到想回去的版本id  (保留五位即可)
git reset hard -- id

六、checkout 进阶与 stash

git checkout -- test.txt :丢弃相对于暂存区最后一次添加的最新内容的工作区修改。简单说就是丢弃工作区的修改

git reset HEAD test.txt :将之前添加到暂存区(stage、index)的内容,从暂存区移除到工作区

关于 checkout 的真相:前面有个图已经说过,git 的管理其实是一个 commit 链。不同的分支指向了不同的节点,checkout 分支 其实也就是在修改 分支指针 所指向的节点。

如果在切换了分支以后,在子分支 dev1 上进行了修改,但是代码的 bug 还没解决完全,此时又来了一个新的需求需要开发;而如果我们直接 chekout 到新的分支 dev2 ,是无法切换的,因为 dev1 相对于 master 分支已经快了一步,此时切换不再是简单的 fast-forward。

通过 commit 来保存修改是可行的,但是按照惯例, commit 的代码应该是没有问题的代码,而此时 dev1 是还未修复完 bug 的,不应该进行提交。此时,stash 就登场了。

stash 主要是用来保存现场和恢复现场的,它将所有需要暂存的修改的信息保存在一个 list 中 ,等需要恢复时使用。

  • 保存现场

    • git stash
    • git stash list
  • 恢复现场

    • git stash apply stash@{0} :将 0 号修改恢复,但是不删除 stash 中的内容

    • git stash pop :恢复并且删除内容

七、标签与 diff

(一)标签

1.何时使用标签?

——当我们的开发进行到一定程度,想对当前版本进行发布时,想要一个一个里程碑式的分界,就可以使用标签。

2.标签有两种:轻量级标签和带有附注的标签。标签就是一个指针,而且不依赖于某个特点分支而存在,所有的分支上都能看到当前存在的标签。

3.标签操作:

  • 创建一个轻量级标签:git tag v1.0.1

  • 创建一个带有附注的标签:git tag -a v1.0.2 -m 'release version'

  • 删除标签:git tag -d tag_name

4.一个很好用的命令 git blame file_name,能清晰地看出 file_name 文件的修改情况以及修改的作者是谁

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MsqMBRdK-1592959258270)(E:\goodgoodstudy\课外书\git learn.assets\image-20200503204812905.png)]

(二)diff——差异性

1.本身 diff 是 Linux 系统自带的内建命令,使用方法:diff file_a file_b ,更清楚的看到差别:diff -u file_a file_b

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nw5Iz3Cu-1592959258276)(E:\goodgoodstudy\课外书\git learn.assets\image-20200503205349041.png)]

含义:

  • ‘-’ 表示源文件,‘+’ 表示目标文件
  • 1,3 :从第一行开始,连续三行
  • 后续为内容行:如果没有符号,表示二者相同;’-‘ 表示把这行删掉能得到目标文件,’+‘ 表示加上这行能得到目标文件

2、git diff 有四种情况

  • 比较暂存区(索引区)和工作区的差别git diff ,此时暂存区的作为原始文件(-),工作区的作为目标文件(+)

  • 比较工作区与 commit_id 对应的提交的差别git diff commit_id ;如果想比较工作区与最新一次提交的差别git diff HEAD ,因为 HEAD 指向当前分支。【原始文件是版本库的,目标文件是工作区的】

  • 比较版本库与暂存区的差别git diff -cached <commit_id> ,如果缺省了 id ,比较的是最新提交和暂存区的差别

  • 比较两个提交的差别git diff commit_id1 commit_id2 ,如果是要比较两个版本下的 src 文件夹的差别:git diff commit_id1 commit_id2 src

默认的原始文件优先级:版本库 > 暂存区

默认的目标文件优先级:工作区 > 暂存区

八、远程与 Github

(一)远程的工作流程

1.借用一个场景来叙述:

张三和李四都在开发一个项目,通过远程来进行合作。

  • 在推送代码时,如果张三首先把代码 push 推送到了远程是可以的,因为远程还是空的;但之后李四想直接 push 是不可以的,因为不可能一直让后来的覆盖前面的
  • 所以此时李四应该先 pull 拉取,同时执行合并 merge,实现了两个人代码的交换。merge 可能会成功:修改的是不同文件,或者是一个文件的不同地方;失败:修改了同个文件的同一行,就需要李四手动进行合并。执行完成之后,李四才可以进行 push 到远程

pull == fetch + merge 【原因之后会说】

2.远程版本库和本地有什么区别吗?

——严格来说,没有。远程的存在只是因为它一直处于开机状态,便于代码交换

3.GitLab 是用于公司内网、局域网开发使用的,从 Github 模仿而来

4.git config 的不同级别:system(整个电脑)、global(用户级别 )、local(仓库级别)。如果配置的是 local ,每次新建仓库都需要重新配置 git config

(二)远程和本地进行关联

1.添加远程地址:git remote add origin https://xxxxx.git ,此处的 origin 以后将代表后面的 url

2.进行第一次关联:git push -u origin master ,-u 表示当前本地分支和远程的 master 分支关联,以后再推送直接 git push 即可

九、Git 远程操作

git remote show :展示本地与之对应的远程仓库(可能不止一个),默认情况下别名都叫 origin ,如果取名 test1、test2 ,也会展示出来

git remote show origin :会列出来远程仓库的详细信息,本地分支和远程分支的 push、pull 关系也会罗列出来

git push 会根据 git config 中的配置来显示不同信息,推送到相应远程分支

使用 git 开发一般是鼓励创建分支的,也有多种开发流程:

  • Gitflow:配置较为复杂,适合于某些场景,具体可见 https://www.cnblogs.com/jeffery-zou/p/10280167.html ,有正在被抛弃的趋势
  • 基于 Git 分支的开发模型:
    • develop 分支:频繁变化的分支,供开发人员 push、merge代码
    • test 分支:供测试、产品等人员使用的一个分支,变化不是特别频繁,merge 自 develop 分支
    • master 分支:生产发布分支,变化非常不频繁的一个分支,merge 自 test 分支,然后直接 push 到远程服务器,进行生产、部署
    • bugfix(hotfix) 分支:生产系统当中出现了紧急 bug,用于紧急修复的分支。从 master 上拉取分支,在这个分支上修复玩再合并到 master

使用 github 来进行远程操作的流程:

  1. 在本地配置个人信息,git config --local user.xxx='xxx'
  2. git remote add origin https://xxxxx.git 关联远程仓库,可以加 https 或者 ssh 的地址,这一步的结果是:将远程仓库的地址写入本地 known_hosts 文件
  3. 如果加的是 ssh 地址,要求在本地生成密钥,将公钥放到 github 上,后续在建立连接时会进行公私钥的匹配。
  4. 如果在放置公钥时,没有勾选添加写权限的勾,则只能从远程 pull 代码(读),但是不能从本地 push 到远程(写)

密钥有针对仓库级别的和账号级别的,后者是同个账户的所有仓库都有效

十、Git 协作

git push 发生了什么?

——当远程分支和本地分支关联后,会在本地存在两个分支:master 和 origin/master ,后者是和远程分支关联的分支。当 push 发生时,首先将本地修改推送到远程,再者修改 origin/master 指向的提交点。(否则,会说 master 比 origin/master 快)

origin/master 是系统自动维护的,我们不能直接操作它。分支指向当前修改,HEAD 指向分支

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值