Git学习笔记

Git安装

linuxhtml

$ sudo yum install git

mac: http://git-scm.com/download/macjava

windows: http://git-scm.com/download/winjquery

git官方文档: https://git-scm.com/book/zh/v2linux

Git安装完以后,须要作最后一步配置,若是你没有作这项配置,是没有git公钥和私钥的,而上传代码到远程仓库的时候须要秘钥进行验证是否本人上传的,想要建立可使用下面的方法:git

打开git bash,分别执行如下两句命令
git config --global user.name “用户名”
git config --global user.email “邮箱”

config 的三个做用域github

--local 只对某个仓库有效
--global 对当前用户全部仓库有效
--system 对系统全部登陆的用户有效
--list

SSH配置

  1. 打开git bash。
  2. 使用cd ~/.ssh能够查看是否已配置SSH。
  3. 执行生成公钥和私钥的命令ssh-keygen -t rsa 并按回车3下(为何按三下,是由于有提示你是否须要设置密码,若是设置了每次使用Git都会用到密码,通常都是直接不写为空,直接回车就行了)。会在一个文件夹里面生成一个私钥 id_rsa和一个公钥id_rsa.pub。(可执行start ~命令,生成的公私钥在 .ssh的文件夹里面)。
  4. .ssh若是不作特殊处理的话,通常是在C:\Users\Administrator目录下。若是看不到.ssh文件,可使用ls -ah指令查看隐藏文件夹便可,这是存放秘钥的文件,打开这个文件会看到id_rsa和id_rsa.pub。id_rsa是私钥文件,id_rsa.pub是公钥文件。
  5. 执行查看公钥的命令cat ~/.ssh/id_rsa.pub

建Git仓库

两种场景:web

1.把已有的项目代码归入Git管理shell

cd 项目代码所在的文件夹
git init

2.创建新的项目直接用Git管理segmentfault

cd 某个文件夹
git init your_project #会在当前路径下建立和项目名相同的文件夹
cd your_project
mkdir 建立目录
echo "" > 文件名 建立文件
clear 清屏

在仓库中添加文件windows

1.将文件拷贝到工做目录

cp ... .

2.测试文件符合要求后添加到暂存目录

git add files
git add -u 全部文件

3.查看文件是否被git管理

git status

4.提交暂存区的文件

git commit -m'更改理由' -am'..'从工做区直接提交

git add 更新将要提交的内容
git restore 放弃工做目录中的更改
git rm 移除

Git和其余版本控制系统如SVN的一个不一样之处就是有暂存区的概念。

工做区(Working Directory)

就是你在电脑里能看到的目录,好比个人learngit文件夹就是一个工做区

版本库(Repository)

工做区有一个隐藏目录.git,这个不算工做区,而是Git的版本库。

Git的版本库里存了不少东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为咱们自动建立的第一个分支master,以及指向master的一个指针叫HEAD

img

git add把文件添加进去,实际上就是把文件修改添加到暂存区;

git commit提交更改,实际上就是把暂存区的全部内容提交到当前分支。

给文件重名名

git mv old new
操做完后commit提交

查看版本历史,提交日志

git log -n5 --oneline 最近5条 简明 
git log --all --graph 全部分支 图像化关系

版本历史图形化工具

gitk
查看分支
git branch -v
建立分支
git checkout -b 分支名 commitid
切换分支
git checkout 分支名

查看某个命令的帮助文档

git help --web 命令  --web 在网页

.git目录

HEAD文件:指向了如今引用的分支

cat HEAD
ref: refs/heads/master

config文件:记录了用户的信息

refs/:引用目录,包含了heads和tags目录

​ tags:标签 里程碑,项目开发到必定程度,给commit打一个标签如[v1.0]

​ 标签文件是tag类型 自己有一个40位的哈希值 ,内容包含了一个commit的类型的object

​ heads:分支,如先后端创建独立的分支,互不影响,须要集成时可合并到一个公共的分支

​ 查看文件对象类型

cat 分支文件
git cat-file -t 哈希值
-p 看内容
若是哈希值足以保证惟一性可使用短的一部分

​ master文件为commit类型

​ git branch -av查看分支能够看到master分支引用指针就是heads目录中master文件的哈希值

objects/:全部文件对象

git在每次commit的时候都会生成一个tree对象、一个parent对象(若是不是第一次提交的话)、和一个commit对象,这个最顶层的tree就是对应整个工做目录,tree下面还有blob、tree对象,都是一串hash值指向对应的内容,当某个文件发生变更的时候会从新保存一次快照(hash),若是文件没有发生变更,保留的快照依然是上次的。

松散对象 (loose object) 会被打包到pack/目录

查看文件对象类型 为:tree

git cat-file -t 文件名+哈希值

查看内容 包含一个blob文件,就是提交的内容

git cat-file -p 文件名+哈希值

git对象彼此的关系

每一次提交都会建立一个commit对象,一个commit对象对应包含一个tree对象,tree表明了当前时间点仓库目录结构的快照,blob指具体的文件,在git中若是两个文件内容相同就看做一个文件,不论文件名

git分离头指针

若是不当心经过git checkout命令切换到某个commit中(即HEAD指向某个commit),git会提示咱们正处于分离头指针的状态下(工做在没有分支的状况下),若是咱们作了大量的修改,可是某天咱们忽然又切换到另外一个commit时,咱们的修改就有可能被git当作垃圾清除掉,所以这个动做十分危险。

分离头指针的用处:进行尝试性的变动时

试着修改某些文件时,若是以为修改的效果不满意,能够直接切换到别的分支,丢弃当前修改

若是咱们切换出去时,以为当前的修改十分重要,就按照git的提示建立一个新分支

若是某个变动(提交)是很是重要的,那么必定要跟某个分支绑定在一块儿

建立新分支:

git checkout -b  新分支名称  基于某个分支或者commit

eg:git checkout -b newBranch master

比较某两个commit的区别

git diff 第一个commit 第二个commit

eg:git diff HEAD HEAD^1  (当前的HEAD指向的commit和他的父级进行比对)

HEAD^ ==HEAD~ == HEAD^1 == HEAD~1

HEAD^^ == HEAD^1^1 == HEAD^2

删除不须要的分支

git branch -D 分支名

修改commit的message

对最近一次commit的message作变动

git commit --amend

更改以前的message

git rebase -i 需更改commit的父级id 
执行后进入编辑,把须要修改的一次message前面的'pick'改成'r'或'reword',保存退出,会跳转到修改message

合并多个连续的commit

git rebase -i 父级commitid
执行后进入编辑,仅保留要合并到的commit的'pick',把须要须要合并的几个'pick'改成's'或'squash',退出保存,修改说明

合并多个间隔的commit

首先git log --graph查看commit历史

变基git rebase -i 父commitid进入vi

将父commitid拷贝进来并改变顺序,放在要合并的commit上面

要合并的commit的'pick'改成's'

pick acf475ed #父commit
s 7ac3c1cb8b92 #要合并的commit
...其余

保存退出后报错:interactive rebase in progress; onto 7ac3c1c

而后执行git rebase --continue继续变基,进入vi

怎加一个message,保存退出便可

其余参考:https://segmentfault.com/a/11...

git处理合并冲突

什么是合并冲突

在 Git 中,“合并(merging)” 是在形式上整合别的分支到你当前的工做分支的操做。你须要获得在另一个上下文背景下的改动(这就也就是咱们所提到过的,一个有效的分支应该是创建在一个上下文工做背景上的),而且合并它们到你的当前的工做文件中来。

做为你的版本管理系统,Git 所带来的最伟大的改善就是它让合并操做变得很是轻松简单。在大多数状况下,Git 会本身弄清楚该如何整合这些新来的变化。

固然,也存在极少数的状况,你必须本身手动地告诉 Git 该怎么作。最为常见的就是你们都改动了同一个文件。即使在这种状况下,Git 仍是有可能自动地发现并解决掉这些冲突。可是,若是两我的同时更改了同一个文件的同一行代码,或者一我的改动了那些被另外一我的删除了的代码,Git 就不能简单地肯定到底谁的改动才是正确的。这时 Git 会把这些地方标记为一个冲突,你必须首先解决掉这些冲突,而后再继续你的工做。
如何解决合并冲突

当面对一个合并冲突时,咱们首先要搞明白发生了什么。例如是否是你和你的同事都同时编辑了同一个文件的同一行代码呢?是否是他删除了一个你正在编辑的文件呢?是否是大家同时添加了一个相同文件名的文件呢?
当你使用 “git status” 时, Git 会告诉你存在一个 “未合并的路径(unmerged paths)”,这只是用另一个方式告诉你,存在一个或多个冲突:

$ git status
# On branch contact-form
# You have unmerged paths.
#   (fix conflicts and run "git commit")
#
# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#
#       both modified:   contact.html
#
no changes added to commit (use "git add" and/or "git commit -a")1234567891011

就让咱们来深刻地探讨一下,如何去解决这些最多见的冲突。
当两个改动发生在同一个文件的同一些行上,咱们就要看看发生冲突的文件的内容了。Git 会很是友好地把文件中那些有问题的区域在 “<<<<<<< HEAD” 和 “>>>>>>> [other/branch/name]” 之间标记出来。

第一个标记后的内容源于当前分支。在尖括号以后,Git 会告诉咱们这些改动是从哪里(哪一个分支)来的。而后有冲突的改动会被 “=======” 分割起来。
如今,当清理文件并获得最终代码后,全部剩下的工做就是将这个结果保存起来,而且立刻退出这个合并工具。这样 Git 就会知道你已经完成了这个操做。Git 会在后台对那个文件自动地执行 “git add” 命令。这也标志着冲突已经解决了。若是你使用合并工具,而是手动在文本编辑器中清理这些冲突,你必须手动地将文件标记为已解决状态(经过执行命令 “git add ”)。

最终,当全部的冲突被解决后,你必须经过一个正常的提交操做来完成这个清理合并冲突的工做。

如何撤销一个合并

你应该始终牢记,你能够在任什么时候间执行撤销操做,并返回到你开始合并以前的状态。要对本身有信心,你不会破坏项目中的任何东西。只要在命令行界面中键入 “git merge –abort” 命令,你的合并操做就会被安全的撤销。

当你解决完冲突,而且在合并完成后发现一个错误,你仍然仍是有机会来简单地撤销它。你只需要键入 “git reset –hard ” 命令,系统就会回滚到那个合并开始前的状态,而后从新开始吧!

git status会有rebase in progress; onto ……这种问题? 该怎么解决?

是你以前或者刚刚用过 git rebase,但上一次的进程尚未完成。

能够直接 git rebase --abort 来取消目前的进程

比较暂存区和HEAD所含文件的差别

git diff --cached

比较工做区和暂存区所含文件的差别

git diff
git diff -- 可加具体文件名

让暂存区恢复成和HEAD同样

git reset HEAD

让工做区恢复为和暂存区同样

git checkout -- 文件名

取消暂存区部分文件的更改

git reset HEAD -- 文件名

消除最近几回的提交

git reset --hard commitid(想回到的commit状态)

查看不一样提交的指定文件的差别

git diff 分支名或commitid 分支名或commitid -- 指定文件

删除文件的正确作法

git rm 文件名

开发中临时加塞了紧急任务怎么处理

场景:开发中有一部分文件已经放到了暂存区,一部分还在工做区修改当中,可是测试发现对应的分支是有问题的,须要临时修复bug

1.先把手头的工做备份到其余地方git stash,能够用git stash list查看

2.修复完bug提交后再恢复继续

git stash apply stash列表中存放的文件仍会保留

git stash popstash列表中存放的文件会移除

指定不须要Git管理的文件

gitHub新建仓库时会让你配置一个.gitignore文件,针对不一样的语言指定不被git管理的文件类型

只能够命名为.gitignore

如java

# Compiled class file
*.class
# Package Files #
*.jar
*.war
*.tar.gz
*.zip
...

将Git仓库备份到本地

经常使用的传输协议

哑协议与智能协议

直观区别:哑协议传输进度不可见,智能协议可见

传输速度:智能协议比哑协议块

推荐使用智能协议

备份特色:多点备份

若是要和远端的仓库进行关联的话,须要remote

git remote -v 查看
git remote add 名字 地址 新建远端仓库

当本地仓库有新的分支,而远端并未添加进去时,直接push

git push 远端仓库

Git远程操做

git clone

远程操做的第一步,一般是从远程主机克隆一个版本库,这时就要用到git clone命令。

$ git clone <版本库的网址>

好比,克隆jQuery的版本库。

$ git clone https://github.com/jquery/jquery.git

该命令会在本地主机生成一个目录,与远程主机的版本库同名。若是要指定不一样的目录名,能够将目录名做为git clone命令的第二个参数。

$ git clone <版本库的网址> <本地目录名>

git clone支持多种协议,除了HTTP(s)之外,还支持SSH、Git、本地文件协议等

git remote

为了便于管理,Git要求每一个远程主机都必须指定一个主机名。git remote命令就用于管理主机名。

不带选项的时候,git remote命令列出全部远程主机。

$ git remote
origin

使用-v选项,能够参看远程主机的网址。

$ git remote -v
origin  git@github.com:jquery/jquery.git (fetch)
origin  git@github.com:jquery/jquery.git (push)

上面命令表示,当前只有一台远程主机,叫作origin,以及它的网址。

克隆版本库的时候,所使用的远程主机自动被Git命名为origin。若是想用其余的主机名,须要用git clone命令的-o选项指定。

$ git clone -o jQuery https://github.com/jquery/jquery.git
$ git remote
jQuery

上面命令表示,克隆的时候,指定远程主机叫作jQuery。

git remote show命令加上主机名,能够查看该主机的详细信息。

$ git remote show <主机名>

git remote add命令用于添加远程主机。

$ git remote add <主机名> <网址>

git remote rm命令用于删除远程主机。

$ git remote rm <主机名>

git remote rename命令用于远程主机的更名。

$ git remote rename <原主机名> <新主机名>

git fetch

一旦远程主机的版本库有了更新(Git术语叫作commit),须要将这些更新取回本地,这时就要用到git fetch命令。

$ git fetch <远程主机名>

上面命令将某个远程主机的更新,所有取回本地。

git fetch命令一般用来查看其余人的进程,由于它取回的代码对你本地的开发代码没有影响。

默认状况下,git fetch取回全部分支(branch)的更新。若是只想取回特定分支的更新,能够指定分支名。

$ git fetch <远程主机名> <分支名>

好比,取回origin主机的master分支。

$ git fetch origin master

所取回的更新,在本地主机上要用"远程主机名/分支名"的形式读取。好比origin主机的master,就要用origin/master读取。

git branch命令的-r选项,能够用来查看远程分支,-a选项查看全部分支。

$ git branch -r
origin/master

$ git branch -a
* master
  remotes/origin/master

上面命令表示,本地主机的当前分支是master,远程分支是origin/master

取回远程主机的更新之后,能够在它的基础上,使用git checkout命令建立一个新的分支。

$ git checkout -b newBrach origin/master

上面命令表示,在origin/master的基础上,建立一个新分支。

此外,也可使用git merge命令或者git rebase命令,在本地分支上合并远程分支。

$ git merge origin/master
# 或者
$ git rebase origin/master

上面命令表示在当前分支上,合并origin/master

git pull

git pull命令的做用是,取回远程主机某个分支的更新,再与本地的指定分支合并。它的完整格式稍稍有点复杂。

$ git pull <远程主机名> <远程分支名>:<本地分支名>

好比,取回origin主机的next分支,与本地的master分支合并,须要写成下面这样。

$ git pull origin next:master

若是远程分支是与当前分支合并,则冒号后面的部分能够省略。

$ git pull origin next

上面命令表示,取回origin/next分支,再与当前分支合并。实质上,这等同于先作git fetch,再作git merge

$ git fetch origin
$ git merge origin/next

在某些场合,Git会自动在本地分支与远程分支之间,创建一种追踪关系(tracking)。好比,在git clone的时候,全部本地分支默认与远程主机的同名分支,创建追踪关系,也就是说,本地的master分支自动"追踪"origin/master分支。

Git也容许手动创建追踪关系。

git branch --set-upstream master origin/next

上面命令指定master分支追踪origin/next分支。

若是当前分支与远程分支存在追踪关系,git pull就能够省略远程分支名。

$ git pull origin

上面命令表示,本地的当前分支自动与对应的origin主机"追踪分支"(remote-tracking branch)进行合并。

若是当前分支只有一个追踪分支,连远程主机名均可以省略。

$ git pull

上面命令表示,当前分支自动与惟一一个追踪分支进行合并。

若是合并须要采用rebase模式,可使用--rebase选项。

$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

若是远程主机删除了某个分支,默认状况下,git pull 不会在拉取远程分支的时候,删除对应的本地分支。这是为了防止,因为其余人操做了远程主机,致使git pull不知不觉删除了本地分支。

可是,你能够改变这个行为,加上参数 -p 就会在本地删除远程已经删除的分支。

$ git pull -p
# 等同于下面的命令
$ git fetch --prune origin 
$ git fetch -p

git push

git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿。

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

注意,分支推送顺序的写法是<来源地>:<目的地>,因此git pull是<远程分支>:<本地分支>,而git push是<本地分支>:<远程分支>。

若是省略远程分支名,则表示将本地分支推送与之存在"追踪关系"的远程分支(一般二者同名),若是该远程分支不存在,则会被新建。

$ git push origin master

上面命令表示,将本地的master分支推送到origin主机的master分支。若是后者不存在,则会被新建。

若是省略本地分支名,则表示删除指定的远程分支,由于这等同于推送一个空的本地分支到远程分支。

$ git push origin :master
# 等同于
$ git push origin --delete master

上面命令表示删除origin主机的master分支。

若是当前分支与远程分支之间存在追踪关系,则本地分支和远程分支均可以省略。

$ git push origin

上面命令表示,将当前分支推送到origin主机的对应分支。

若是当前分支只有一个追踪分支,那么主机名均可以省略。

$ git push

若是当前分支与多个主机存在追踪关系,则可使用-u选项指定一个默认主机,这样后面就能够不加任何参数使用git push

$ git push -u origin master

上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就能够不加任何参数使用git push了。

不带任何参数的git push,默认只推送当前分支,这叫作simple方式。此外,还有一种matching方式,会推送全部有对应的远程分支的本地分支。Git 2.0版本以前,默认采用matching方法,如今改成默认采用simple方式。若是要修改这个设置,能够采用git config命令。

$ git config --global push.default matching
# 或者
$ git config --global push.default simple

还有一种状况,就是无论是否存在对应的远程分支,将本地的全部分支都推送到远程主机,这时须要使用--all选项。

$ git push --all origin

上面命令表示,将全部本地分支都推送到origin主机。

若是远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地作git pull合并差别,而后再推送到远程主机。这时,若是你必定要推送,可使用--force选项。

$ git push --force origin

上面命令使用--force选项,结果致使远程主机上更新的版本被覆盖。除非你很肯定要这样作,不然应该尽可能避免使用--force选项。

最后,git push不会推送标签(tag),除非使用--tags选项。

$ git push origin --tags
相关文章
相关标签/搜索