Git学习笔记

git学习笔记

主要是学习:https://www.yiibai.com/git 的笔记,较之于网上的其他教程,此教程兼顾了原理和用法,同时命令涉及的更加全面。

概念:

image.gif

Workspace:工作区

Index/Stage:暂存区,也叫索引

Repository:仓库区(或本地仓库),也存储库

Remote:远程仓库

传统的代码管理工具,比如SVN,如下图所示,主要是记录变化量:

image.gif

git不同,直接保存文件,也就是记录文件快照:

image.gif

      为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。反应到上图,虚线表示文件没有修改,对应版本就只需要记录一个指针引用即可。实线表示有修改,git直接新建一个完整的文件进行维护。

     工作目录下的每一个文件都不外乎这两种状态:已跟踪或未跟踪。 已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区。 工作目录中除已跟踪文件以外的所有其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。 通过git add命令将untracted文件转换成tracked文件。

 

image.gif

每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。

在 Git 中任何已提交的东西几乎总是可以恢复的。甚至那些被删除的分支中的提交或使用 --amend 选项覆盖的提交也可以恢复。然而,任何你未提交的东西丢失后很可能再也找不到了。

git 的工作流程:

image.png

 

命令:

  • git config:对git进行配置,git的配置文件分别在:etc/gitconfig,~/.gitconfig,.git/config,分别是系统级别,用户级别和仓库级别的git设置,后者和前者有冲突,会使用后者进行覆盖。
  • git config --list:列出所有的配置信息
  • git status

运行 git status -s,状态报告输出如下:

$ git status -s
 M README.md
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt

image.gif

新添加的未跟踪文件前面有 ?? 标记

新添加到暂存区中的文件前面有 A 标记

修改过的文件前面有 M 标记。 你可能注意到了 M 有两个可以出现的位置,出现在右边的 M 表示该文件被修改了但是还没放入暂存区,出现在靠左边的 M 表示该文件被修改了并放入了暂存区。

  • ignore文件的编写  GitHub 有一个十分详细的针对数十种项目及编程语言的 .gitignore 文件列表,你可以在 http://github.com/github/gitignore 找到它。
  • git diff可以显示工作区文件和缓存区文件的修改差异,但是内容不够直观,可以使用git difftool命令直观显示差异:

image.gif

 

git diff 默认显示的是工作区和缓存区文件修改的差异,但diff还可以显示其他:

git diff --cached 查看已经缓存起来文件和上次提交的快照HEAD之间的差异

git diff HEAD显示工作区和HEAD的区别

git diff master dev 显示master和dev分支的区别

git diff dev...master 显示从master分出dev分支后和现在master之间的差异

git diff dev 显示当前分支和dev分支的区别

git diff HEAD HEAD^ 显示上次提交和上上此提交的差别

git diff SHA1 SHA2 显示两次提交的差异

git diff --stat 仅仅显示统计信息,而不是全部信息

  • git rm 从暂存区和工作区删除文件,并且不再追踪相应文件
  • git rm --cached 只从暂存区删除文件,工作区保留文件,不再追踪相应的文件

      也可以直接使用命令  git reset HEAD file_name 达到相同的目的

  • git log -p --graph --oneline -2

-p显示每一次提交的修改信息

--graph 图形化显示

--oneline 简短显示

-2 只显示最近2次提交

其他选项见:https://www.yiibai.com/git/git_log.html#article-start

 

git log --graph --oneline 的结果如下:

Screen Shot 2020-07-26 at 7.40.13 PM.png

什么含义呢?所谓的graph主要由-和*构成,总体上可以看出分支的分离和聚合,每一个*对应于一条commit信息。反过来,每一条commit信息对应的*在哪一个分支上,就是哪一个分支的提交。

git checkout 会新建分支,出现上图所示的分叉。两个不同的用户从同一个仓库 git clone也会分叉。其实git简化了问题,只要可能产生不同的文本,都是分支。对于两个人git clone的情况,可以这样理解:远程origin/master映射到了user1的origin/master分支和user2的origin/master分支。

  • git commit --amend 进行commit修改,可以增加commit的文件,改变提交信息,但是依然是同一个commit
  • git commit -a 可以跨过git add直接提交,但是前提是相应文件已经被追踪过。简而言之,被git add过的文件之后做出修改,可以直接使用commit -a进行提交。
  • git checkout -- file_name 撤销对文件的修改,工作区对应文件恢复到上一次commit版本,在git status中会有此命令的提示
  • git remote -v 显示远程仓库名字以及对应的URL
  • git remote add <shortname> <url> 添加远程仓库
  • git fetch 仅仅拉取还没有的数据,但是并不做合并
  • git pull 从对应分支拉取数据并合并。注意,git pull只拉取当前分支,如果拉取所有分支,git pull --all

git pull origin dev 将远程的origin仓库的dev分支拉取到当前分支

git pull origin dev:master 将远程的origin仓库的dev分支拉取到master分支

  • git push remote_name branch_name 。git push只push当前分支,如果push所有分支,git push --all
  • git remote show origin 显示remote 的 origin服务器信息

image.gif

显示的的信息都非常有用:

当前处于master分支,如果是push,本地分支会被推到哪些远程分支,如果pull,从远端拉取哪些分支与本地分支进行融合。

  • git reomte rename origin likes 将远程仓库名字从origin修改成likes
  • git remote rm origin 删除origin分支
  • git show SHA1 显示对应SHA1的commit的更改
  • git stash 隐藏工作区/缓冲文件(未提交的修改或删除文件,新增添的文件无效)  git stash list 列出所有的stash   git stash pop恢复工作区修改
  • 通过git reset切换HEAD,用于恢复到某一个提交点上
  • git checkout file_name将文件恢复到缓冲区中的样子,缓冲区中没有,则恢复到最近的提交点, git checkout -- file_name将文件恢复到缓存区的样子

git checkout SHA1 file_name将文件通过SHA1恢复到指定提交版本的样子,也可以用HEAD代替最近一次提交的SHA1值

  • git tag 每次使用SHA1来标识commit过于繁琐,可以对关键的commit简历tag。
  • git branch -vv 查看本地分支与远程分支的对应关系:

Screen Shot 2020-07-26 at 4.12.18 PM.png

表示本地的dev分支对应于远程的origin/dev分支,本地的master分支对应于远程的master分支。最后的信息表示commit信息。

  • git冲突解决详解:

如果有多个人一起对同一分支进行开发,则可能出现冲突。开始两人基于同一commit位置进行开发,甲完成后git push成功。乙后面完成,git push会报错:

Screen Shot 2020-07-26 at 5.09.29 PM.png

使用git的要义在于不要心急,仔细阅读提示信息,按照提示去做不会有大问题。如果一时猴急,后面会有无尽的血与泪!!!

上面的报错讲的很清楚了:报错原因在于远端包括了本地没有的工作,也就是乙的本地没有包括甲已经push上去的工作。解决方法也说的很清楚了,要先整合远端的修改。具体做法就是在再次push之前先执行git pull:

Screen Shot 2020-07-26 at 5.13.41 PM.png

如上图所示,git pull后git会自动merge,但是merge冲突失败了,我们需要手动解决冲突:Screen Shot 2020-07-26 at 5.15.07 PM.png

<<<<<和=====之间的是本地文本,=====和>>>>>>之间的是远程文本,根据需要做出修改即可:

Screen Shot 2020-07-26 at 5.17.05 PM.png

之后git commit ,git push成功。

Screen Shot 2020-07-26 at 5.18.44 PM.png

第二种情况是乙在甲push之后,在工作区做出了部分修改,在git add之前pull:

Screen Shot 2020-07-26 at 5.22.58 PM.png

重要的事情说三遍,一定要仔细阅读git信息,尤其是操作失败的时候。error信息讲的明明白白:乙本地修改的文件可能被覆盖(丢失)。git建议我们使用stash或者commit:

先试一下git stash:

Screen Shot 2020-07-26 at 5.26.55 PM.png

如上图所示,使用stash后,git隐藏了本地修改,数据和上一次提交版本一样,所以git pull顺利完成。之后使用stash pop把隐藏的数据pop出来:

Screen Shot 2020-07-26 at 5.28.48 PM.png

如上图显示,有冲突,我们cat看一下test文件的变化:

Screen Shot 2020-07-26 at 5.29.45 PM.png

解决上图所示的冲突后,commit ,push顺利完成Screen Shot 2020-07-26 at 5.31.54 PM.png

正如git提示所说的那样,我们除了使用stash之外,也可选择先commit,之后再pull,具体做法在前面已经详细介绍了。虽然stash和commit两种方法都可以,但是个人觉得使用先commit的方法要更为妥当一些,因为在git中,只要是commit过的文件,就意味有永久快照,始终可以找回来。

git本质上是一个工具而已,看的再多也不如动手操练一下,冲突解决的学习可以直接git clone同一个库两份,模拟两个人对同一个文件进行修改后push。多操作几次就烂熟于胸了。

  • 分支合并详解,想把分支dev合并到分支master,先checkout到分支master,之后git merge dev即可:

Screen Shot 2020-07-26 at 5.52.56 PM.png

如上图所示,通过git status可以看到,对工作区和缓冲区没有任何影响,git log一下:Screen Shot 2020-07-26 at 5.56.39 PM.png

如上图所示,只是将分支dev从master分离后的所有commit拼接在了master分支上。

现在构造合并分支冲突并介绍解决方法:

从分支master分出dev分支,然后分别在dev和master分支中对相同的文件做出相应的修改,分别add,commit,之后切换到master分支,执行命令git merge dev:

Screen Shot 2020-07-26 at 7.19.42 PM.png

如上图所示,发生了冲突,git status查看哪里有问题:Screen Shot 2020-07-26 at 7.24.39 PM.png

git信息讲的很清楚,也提供了相应的解决方案。先试一下git merge --abort:

Screen Shot 2020-07-26 at 7.26.40 PM.png

master分支完全回到merge之前,没有任何变化。再来试一下解决冲突:

Screen Shot 2020-07-26 at 7.28.01 PM.png  ==>Screen Shot 2020-07-26 at 7.28.36 PM.png

执行命令git merge dev:

Screen Shot 2020-07-26 at 7.30.05 PM.png

如上图所示,依然报错。之前说什么来着?仔细阅读git 信息,git可没说冲突解决后再次执行git merge进行合并,而是执行git add或者git rm来标识为已解决冲突,然后commit:

Screen Shot 2020-07-26 at 7.34.59 PM.png

在看一下日志:

Screen Shot 2020-07-26 at 7.37.46 PM.png

合并已经成功了。

当然我们也可以直接 git rm test,删除冲突文件后提交。但是这显然在实际情况中比较少见。

  • git 回撤详解。git的回撤主要通过git reset命令实现:

git reset 回滚git add操作,工作区保持不变,缓冲区还原。就是git add的逆操作

git reset HEAD^ --soft 回滚最后一次提交,但是工作区和缓冲区保持不变

git reset HEAD^ --hard 回滚最后一次提交,工作区,缓冲区全部还原到上一次提交。通常不建议使用hard选项,这意味着会永久丢失工作区的更改(如果没有提交的话)。对于git而言,只要commit过,永远都有方法找回来。如果commit过,通过git reflog或者git log -g找到对应SHA1 就可以 git reset回来,如果直接git reset SHA1,默认是mixed,也就是恢复到缓冲区,工作区不会有变化,还需要git checkout -- file_name还原到工作区,如果git reset SHA1 --hard就可以直接还原到工作区。

其他情况需要时参看:https://www.yiibai.com/git/git_reset.html#article-start

git rebase 命令用于简化commit有一定意义,但是修改了历史记录比较危险。建议如下:

1、无论如何不能rebase已经push到远程的commit

2、最好只将较长的commit单线rebase成较短的commit,也就是不要rebase分支

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值