0%

Git与GitHub的使用

git真的是一个很方便的一个工具,非常值得学习,而且搭配github使用或者是多人项目的开发,真的是很牛x。

分布式与集中式

学习之前了解一下分布式与集中式
假如我们要办一件事,一个人包揽就是集中式,一件事分成几个部分分成几个人做就是分布式,二者最取得的效果是一样的。
比如一个javaweb的项目,我们把它简单的分成web页面服务:数据库服务,service服务。

集中式: 我们将它部署在服务器上,如果服务器出了问题,这个网站就崩了。

分布式: 上面的三个,我们用独立服务器放,同一类我们还可以用多个服务器组成,即使一个崩了,还有其他的服务器顶着。

集中式版本控制: 版本库存放在中央服务器,每次工作都要从中央服务器取出最新的版本,修改以后再提交上去,一旦服务器崩了,或者没网了,工作无法执行。
分布式版本控制: 没有中央服务器,每个人的电脑上都有一个完整的版本库,每次工作完以后只要将每次的修改提交给对方就行了。

git的使用

git使用前的最小配置

git config –global user.name ‘your_name’
git config –global user.email ‘your_email@domain.com’
缺省等同于local

  • git config –local local只对某个仓库有效
  • git config –global global对当前用户的所有仓库有效
  • git config –system system对系统所有登录的用户有效

在当前仓库中,如果设置了local的话,local优先级要高,system指令用不上

查看一些配置信息:

  • git config –list –local 只在某一个仓库有效
  • git config –list –global 所有仓库有效
  • git config –list –system

了解工作区,暂存区,历史版本库

分区

git是如何保存数据的

git存储文件的方式不是存储文件的变化或者差异,他存储的是一系列不同时刻文件的 快照 .例如,每次你执行 git add 或者 git commmit 操作,就会将文件压缩成一个二进制文件,这就是一个Git对象,存在于 ==.git/objects== 目录下。文件的名字是用SHA1算法计算的一个hash值(长度40的字符串), ==.git/objects== 下成一个子目录,前两个字符是子目录名,后38位是文件名。

.git文件

两个比较重要的文件:

refs/

heads -分支 (例如:前端分支,后端分支,两者互不影响)
tags -里程碑 (标签)

HEAD - 查看当前仓库在哪个分支上
conig - 仓库信息
objects - 存储每次操作的二进制文件

git中文件的几种状态

Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.

Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified.

Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过,返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改

Staged: 暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename 取消暂存,文件状态为Modified

git的常用操作

1. 查看工作区状态

1
git status

2. 工作区提交到暂存区

对暂存区文件的修改:添加,删除,更新

1
2
3
4
5
git add <file-name>
git add . //提交所有文件

git add --ignore-removal //不提交删除文件
git add -u //不提交新文件

3. 暂存区提交到版本库

1
git commit -m 'message'

4. 查看历史版本

1
2
3
4
git log                             //查看所有版本历史
git log <branch-name> //查看当前分支
git log --graph //以图的形式查看版本历史
git log --oneline //省略一些信息,一次commit只展示一行

5. 比较文件差异

1
2
3
git diff [--<file-nameA> [<file-nameB>]]                //比较工作区与暂存区差异,加文件名就只比较文件(可以比多个)的差异

git diff -cached [--<file-nameA> [<file-nameB>]] //比较暂存区与head指针所含文件的差异

6. 删除工作区和暂存区文件

1
git rm <file-name>

7. 工作区同步与暂存区一样

1
2
git checkout -- <file-nameA> [file-nameB]
git checkout -- *

8. 暂存区同步与历史版本库一样

1
2
git reset <branch-name>                     //同步到某一个分支
git reset HEAD -- <filenameA> [filenameB] //同步到某一个分支的一个或者多个文件

9. 版本回溯

1
2
git reset --soft <commit-id>
git reset --hard <commit-id>
git reset 影响范围
指令 HEAD 暂存区 工作区
--soft
--mixed
--hard

10. 合并分支

– 基于 merge

1
git merge <merge-nameA>
1
git merge --abort   //如果不想合并,此命令会返回合并之前的状态

fast-forward(快进)与non-fast-forward
分支合并,其中一个分支,是另外一个分支的父分支,叫做fast-forward,否则就是non-fast-forward

merge操作:利用三路合并算法,merge结果与时间先后无关,就是两个人分支会找到一个基准Base(历史版本中的某一次commit,简单情况下就是分支分叉的位置),如果两个文件相对于Base都不一样,就会产生冲突,需要手动解决。查看两个分支的Base命令: git merge-base <merge-nameA> <merge-name-B>merge之前的文件在merge过程中可以导出查看

– 基于 rebase的变基操作

将一个分支的修改移到另外一个分支上,好像”重新播放”一样.

1
2
3
4
5
git rebase <branchA>        //相当于在B分支上,把B整合到A上,A,B最近的共同父分支(就是分叉的位置)往后的B分支都不见了,会在A分支后生成一段新的提交。这样,提交历史就是一条干净的直线了。

//如果发生冲突
git add .
git rebase --continue

最好是在提交到远程仓库之前之前,将自己的版本库进行一次变基操作,再向主项目提交。
变基操作的准则:不要对在你的仓库外有副本的分支执行变基。

11. 修改工作区和暂存区文件名

1
git mv <old-name> <new-name>

12. 关于分支的操作

– 创建分支

1
git branch <new-branch-name>

– 查看分支

1
git branch [-v]

– 切换分支

1
git checkout <branch-name>

– 删除分支

1
git branch -d <branch-name>

13. 将多个commit整理成一个commit

– 不连续的commit

1
git rebase -i <要整合的最早的一个commit>

演示:
先看一段版本历史:
版本历史
容易看出版本号为: d09341c ,e3a6b32 ,603e2b3 都是对readme.md的操作,我们想整理成一次commit。
先找到要整合的最早的commit的版本号 为 603e2b3
执行:git rebase -i 603e2b3
进入界面:
版本历史
修改后:
注意看p,s均为简写,下方有注释
版本历史

退出后,执行 git rebase --continue

进入界面:
版本历史
添加注释:
版本历史

-- 连续的commit

1
git rebase -i <整合的最早的一个commit>

类似上方,更简单。

14. 消除最近的几个commit

1
git reset --hard <commit-number>        //工作区和暂存区都会恢复成指定的commit版本号的内容(慎用)

15. 开发中如果紧急加塞怎么处理

git stash会将此时工作区和暂存区的内容压入Git的栈中,工作区就是干净的了,此时工作区的内容会和上次的commit内容一样。来避免一次脏提交。

1
2
3
4
5
6
git stash:                      //备份当前的工作区和暂存区的已经被track的文件,保存到Git栈中。从最近的一次提交中读取相关内容,让工作区保证和上次提交
git stash save "message" //同上并添加备注信息
git stash list: //显示git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。
git stash pop stash@{0} //从git栈中读取并恢复工作区,然后删除对应的记录,默认恢复最新的(stash@{0}为最新)
git stash apply stash@{0} //同git stash pop,但不会删除对应的记录
git stash clear //清空git栈。此时使用gitg等图形化工具会发现,原来stash的哪些节点都消失了。

多人协作以及GitHub的使用

git备份

哑协议与智能协议
直观区别:哑协议传输进度不可见;智能协议传输可见
传输速度:智能协议比哑协议传输速度快

常用协议 语法格式 说明
本地协议(1) /d/Desktop/gitcommit/commit2/.git 哑协议
本地协议(2) file:///d/Desktop/gitcommit/commit2/.git 智能协议
http/https协议 https://github.com/name/learngit.git 平时接触到的都是智能协议
ssh协议 git@github.com:name/learngit.git 工作中最常用的智能协议

多人协作

git clone的使用

  • git clone <版本库的网址> [file-name]
    如果附带[file-name],则会生成一个目录名字为[file-name],默认则为版本库的名字。(注意网址后面是附带.git的)

git remote的使用

  • git remote [-v]
    查看远程主机 [与网址]
  • git remote add <主机名> <网址>
    添加主机
  • git remote rename <原主机名> <新主机名>
    修改主机名字
  • git remote rm <主机名>
    删除主机
  • git remote show <主机名>
    查看主机信息

git fetch的使用

  • git fetch <远程主机名> [分支名]
    取回远程主机所有分支的更新(若附带括号则取指定分支名的更新)

git push的使用

git push <远程主机名> [远程分支名]:[本地分支名]

git pull的使用

  • git pull <远程主机名> <远程分支名>:<本地分支名>
    取回远程主机的指定分支,并与指定本地分支合并(一个git pull操作等于先git fetch再git merge)

在git clone的过程中,Git会在本地分支与远程分支之间建立一种追踪关系(tracking)。例如,git clone过程中,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master分支自动"追踪"origin/master分支。

Git也允许手动建立追踪关系

git branch --set-upstream <本地分支名> <远程仓库名>/<远程分支名>

如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名。

git pull <远程仓库名>

第一次提交到非空GitHub仓库

例如:github初始化时,带有readme和开源协议
记得git pull一下

不同人的人修改了不同的文件

1
2
3
4
5
6
7
8
$ git push github chase
To github.com:shanqianyouyu/Learning.git
! [rejected] chase -> chase (non-fast-forward)
error: failed to push some refs to 'git@github.com:shanqianyouyu/Learning.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

先 merge一下再push

不同的人修改了相同文件的不同位置

同上,git会自己整合

不同的人修改了相同文件的相同位置

同上操作,不过此时,会提示冲突,git会自己整合,但是需要自己解决冲突

不同的人同时变更了文件名和文件内容

例如:

  1. (先)A修改 index.htmlindex.htm 并且 push到远程仓库
  2. (后)B修改 index.html (B不知道文件名已经被修改了),并且修改了文件的内容,push到远端,发现错误,git pull(等同于上面的 git fetch 再 git merge) 一下,发现git自动识别出来,就是git会将B仓库下的 index.html 修改成 index.htm ,并且内容被修改,再push到远程仓库即可

不同的人同时修改了文件名

  1. (先)A修改了 index.htmlindex1.html ,并且push到远端
  2. (后)B修改 index.htmlindex2.html ,push到远端报错, git pull 到本地,发现发生冲突,这时候需要手动解决冲突, git status 会发现,工作区有两个文件 index1.html index2.htmlgit status 发现暂存区提示
    1
    2
    3
    both deleted:    index.html
    added by them: index1.html
    added by us: index2.html
    这时候你需要和你的同伴讨论最后的名字是哪一个,然后手动删除不需要的两个文件,提交另外一个即可,再 git push 到远程仓库。

FETCH_HEAD

FETCH_HEAD是一个短期引用,以跟踪刚刚从远程存储库获取的内容。 git pull首先调用git fetch,在正常情况下从远程获取一个分支; FETCH_HEAD指向这个分支的提示(它存储提交的SHA1,就像分支一样)。 git pull然后调用git merge,将FETCH_HEAD合并到当前分支。

团队协作中禁止的操作

  • git push -f
  • 禁止向集成分支执行变更历史操作(变基操作)

如何在Github上找到想要的开源项目呢

进入链接https://github.com/search/advanced
或者在搜索栏空搜,git的搜索功能.png
github的help中有教怎么用,或者看看这个链接吧.

1
2
3
4
补充:https://www.jianshu.com/p/450cd21b36a4
#允许提交包含混合换行符的文件
git config --global core.safecrlf false
windows平台下使用git add,git deploy 文件时经常出现“warning: LF will be replaced by CRLF” 的提示。
iBoy wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!