Git学习指南

Git命令速查表

命令速查表

Git介绍

版本控制系统 VCS(Version Control System)

  • Git是一个免费开源的分布式版本控制系统(DVCS)
  • Git是一个基于内容寻址的存储系统

GitHub就是一个免费托管开源代码的远程仓库。

Git特性

  1. 完全的分布式
  2. 轻量级的分支操作
  3. Git已经成为现实意义上的标准
  4. 社区成熟活跃

Git 与常用的版本控制工具CVS、Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。

Git 与 SVN 区别

  1. Git 是分布式的,SVN不是:这是Git 和其它非分布式的版本控制系统如SVN,CVS等最核心的区别。
  2. Git 把内容按元数据方式存储,而SVN是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn和.cvs等文件夹里。
  3. Git分支和SVN的分支不同:分支在SVN中不特别,就是版本库中的另外的一个目录。
  4. Git没有一个全局的版本号,而SVN有:目前为止,这是跟SVN相比GIT缺少的最大的一个特征。
  5. Git 的内容完整性要优于SVN:Git 的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

Git仓库模型

与svn最主要的区别在于大多数VCS(如svn)都是保存基于文件变化的列表数据,如p1.png。但是git不是这样的,当你提交一个版本状态到git时,相当于做了一个镜像,这个镜像保持和你提交的内容一致,为了高效,如果某个文件未改动,则git不会再在镜像中保存重复的文件,而是link到之前已存储的文件如p2.png。
git使用sha-1来check区分文件,实际上git保存所有数据都是依据该hash而不是使用文件名。
在git的所有操作中,都是对git数据库的增加操作,包括删除文件等操作,这是为了保证所有的操作都能够undo。

Git工作流程

Git学习指南_第1张图片
Git工作流程图

一般工作流程如下:

  1. 将Git的一个存储库克隆为工作副本。
  2. 可以通过添加/编辑文件修改工作副本。
    如有必要,还可以通过让其他开发人员一起来更改/更新工作副本。
  3. 在提交之前查看更改。
  4. 提交更改:如果一切正常,那么将您的更改推送到存储库。
  5. 提交后,如果意识到某些错误并修改错误后,则将最后一个正确的修改提交并将推送到存储库。

分支

从目标仓库获得一份项目拷贝,每条拷贝都有和原仓库功能一样的开发线。

分支模型(branching model)/ 工作流(workflow):
一个围绕项目【开发/部署/测试】等工作流程的分支操作(创建、合并等)规范集合。

产品级的分支模型

常驻分支 development

  • 从master创建
    production(master)
  • 默认分支

活动分支 feature

  • 从development创建
    hotfix 如hotfix-36(代码bug修复分支)
  • 从master创建
    release 如release-110
  • 从development分支创建

Git命令

git config

用于获取并设置存储库或全局选项,这些变量可以控制Git的外观和操作的各个方面。

  • local 默认 高优先级:只影响本仓库
  • global 中优先级:影响到所有当前用户的git仓库
  • system 低优先级:影响到全系统的git仓库
git config --global user.name "Your Name"
git config --global user.email "[email protected]"

用了这个参数表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。

如果想要检查你的配置,可以使用 git config --list 命令来列出所有 Git 当时能找到的配置。

你可以通过输入 git config 来检查 Git 的某一项配置。

$ git config user.name
John Doe
  • ssh-keygen
    默认情况下,用户的 SSH 密钥存储在其 ~/.ssh 目录下。

git init

git init 命令执行完后会在当前目录生成一个 .git 目录,使用我们指定目录作为Git仓库。

git init repo

初始化后,会在repo 目录下会出现一个名为 .git 的目录,所有Git需要的数据和资源都存放在这个目录中。如果你没有看到.git目录,那是因为这个目录默认是隐藏的,用
ls -ah命令就可以看见。

git add

添加文件内容到暂存区(同时文件被跟踪)

$ git add .  # 将所有修改添加到暂存区
$ git add *  # Ant风格添加修改
$ git add *Controller#将以Controller结尾的文件的所有修改添加到暂存区
$ git add Hello*   # 将所有以Hello开头的文件的修改添加到暂存区 例如:HelloWorld.txt,Hello.java,HelloGit.txt ...
$ git add Hello?   # 将以Hello开头后面只有一位的文件的修改提交到暂存区 例如:Hello1.txt,HelloA.java;如果是HelloGit.txt或者Hello.java是不会被添加的
# 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new)
git add -u 

git commit

根据暂存区内容创建一个提交记录,只负责把暂存区的修改提交了。

# -m后面输入的是本次提交的说明
git commit -m "提交记录文字"

添加文件到Git仓库,分两步:

  1. 使用命令git add ,注意,可反复多次使用,添加多个文件;
  2. 使用命令git commit -m ,完成。

修改提交说明

git commit --amend -m "edit"

给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存 起来一并提交,从而跳过git add步骤。

你提交后发现忘记了暂存某些需要的修改,可以像下面这样

  $ git commit -m 'initial commit'
  $ git add forgotten_file
  $ git commit --amend

最终你只会有一个提交 - 第二次提交将代替第一次提交的结果。

git commit -am = git add + git commit -m

git status

查看目录,对状态的跟踪,用于显示工作目录和暂存区的状态。

git status -s 状态简览

  • 未跟踪<>跟踪
  • 工作目录 <> 暂存区
  • 暂存区 <> 最新提交
Git学习指南_第2张图片
示意图

Git 项目的三个工作区域的概念:Git 仓库、工作目录以及暂存区域

  • Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。

  • 工作目录是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘
    上供你使用或修改。

  • 暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。有时候也被称作“索引”,不过一般说法还是叫暂存区域。

基本的 Git 工作流程如下:

  1. 在工作目录中修改文件。
  2. 暂存文件,将文件的快照放入暂存区域。
  3. 提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。

这三个区的转换关系以及转换所使用的命令:

Git学习指南_第3张图片
转换关系
Git学习指南_第4张图片
git工作流

git log

显示从最近到最远的提交日志

  • git log --pretty=oneline

--pretty=oneline,只会显示版本号和提交时的备注信息

git reflog

用来记录你的每一次命令

git diff

显示不同版本差异

  • git diff 显示工作目录与暂存区的差异
  • git diff --cached 或者 git diff --staged 显示暂存区与上次提交快照的差异,默认为HEAD
  • git diff master branchB 比较master分支和branchB分支之间的差异

git checkout --file

将文件从暂存区恢复到工作目录

git reset --file

将文件从提交区恢复到暂存区

添加远程仓库

  • git remote add
    添加一个新的远程Git仓库。

分支操作

git branch 分支的增删查改

$ git branch
  iss53
* master
  testing

注意看 master 分支前的*字符:它表示当前所在的分支。也就是说,如果现在提交更新,master 分支将随着开发进度前移。若要查看各个分支最后一个提交对象的信息,运行 git branch -v。

要从该清单中筛选出你已经(或尚未)与当前分支合并的分支,可以用 --merged 和 --no-merged 选项

  • git branch -v 查看分析信息
  • git branch -a 绿色代表当前项目所在的分支,红色就是远程分支列表
  • git branch -r 查看远程分支
新建一个远程分支

先在本地准备好一个新的分支, 例如本地先准备好了一个新分支: feature-M5-2:

$ git branch
  develop
* feature-M5-2

然后在把本地分支发布到远程库里面

git push origin feature-M5-2

git clone

将存储库克隆到新目录中。

克隆仓库的命令格式为:

git clone 

如果我们需要克隆到指定的目录,可以使用以下命令格式:

git clone  

参数说明:

  • repo:Git 仓库。
  • directory:本地目录。

git clone默认会把远程仓库整个给clone下来
但只会在本地默认创建一个master分支
如果远程还有其他的分支,此时用git branch -a查看所有分支。

git help

显示有关Git的帮助信息。

git merge

用于将两个或两个以上的开发历史加入(合并)一起。

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

假设我们在dev分支上开发

step 1: 切换到master分支

checkout out master

step 2: 把远程master上的代码pull下来

git pull origin master

step 3: 合并dev分支到master

git merge dev

step 4: 查看状态

git statas

step 5:将commit push到远程分支master上

git push origin master

撤销合并
方法1:

  • 退出合并,用于合并时出现冲突但不想现在解决冲突 git merge --abort

方法2:

  • step 1:找到最后一次提交到master分支的版本号,即【merge前的版本号】
    git log --pretty=oneline

  • step 2:会退到某个版本号
    git reset --hard 【merge前的版本号】

git fetch和git pull的区别

  • git fetch:相当于是从远程获取最新版本到本地,不会自动合并。
  • git pull:相当于是从远程获取最新版本并merge到本地。

git push 推送分支

远程仓库名字 “origin” 与分支名字 “master” 一样,在 Git 中并没有任何特别的含义一样。
同时 “master” 是当你运行 git init 时默认的起始分支名字,原因仅仅是它的广泛使用,
“origin” 是当你运行 git clone 时默认的远程仓库名字。

推送分支就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:

$ git push origin master

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

如果要推送其他分支,比如dev,就改成:

$ git push origin dev

多人在同一个分支上协作时,很容易出现冲突。即使没有冲突,后push的童鞋不得不先pull,在本地合并,然后才能push成功。

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

这个是push的完整写法,将本地分支上传到远程分支,例如:

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

如果省略了<远程主机分支名> 即:

git push dev 

则git会push到远程分支的同名本地分支,即和

git push dev:dev

等价。如果远程分支dev不存在则会创建dev分支。

$ git push

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

推送本地分支local_branch到远程分支remote_branch并建立关联关系

  • 远程已有remote_branch分支并且已经关联本地分支local_branch且本地已经切换到local_branch

git push

  • 远程已有remote_branch分支但未关联本地分支local_branch且本地已经切换到local_branch

git push -u origin/remote_branch

  • 远程没有remote_branch分支且本地已经切换到local_branch

git push origin local_branch:remote_branch

git remote -v

查看关联的远程仓库的详细信息

pwd

用于显示当前的目录

mkdir XX

创建一个空目录,XX指目录名

cat XX

查看XX文件内容

git --version

查看git版本信息

撤销修改

git reset  --hard HEAD^ 
git reset  --hard HEAD~ 

回退到上一个版本

如果想回退到100个版本,使用git reset –hard HEAD~100
HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令

git reset --hard commit_id
  • 场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file。

  • 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD ,就回到了场景1,第二步按场景1操作。

  • 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。

在被 git 管理的目录中删除文件时,可以选择如下两种方式来记录删除动作:

  1. rm + git commit -am "abc"
  2. git rm + git commit -m "abc"

编辑冲突

<<<<<<< HEAD

=======

>>>>>>> iss53

可以看到 ======= 隔开的上半部分,是 HEAD(即 master 分支,在运行 merge 命令时所切换到的分支)中的内容,下半部分是在 iss53 分支中的内容。解决冲突的办法无非是二者选其一或者由你亲自整合到一起。比如你可以通过把这段内容替换为下面这样来解决:


这个解决方案各采纳了两个分支中的一部分内容,而且我还删除了 <<<<<<<,======= 和 >>>>>>> 这些行。在解决了所有文件里的所有冲突后,运行 git add 将把它们标记为已解决状态(译注:实际上就是来一次快照保存到暂存区域。)。因为一旦暂存,就表示冲突已经解决。

git stash

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

基础命令:
do some work
$git stash pop

Git常见问题

Fast-Forward

bugfix分支是从master分支分叉出来的。


Git学习指南_第5张图片
合并前

合并 bugfix分支到master分支时,如果master分支的状态没有被更改过,那么这个合并是非常简单的。 bugfix分支的历史记录包含master分支所有的历史记录,所以通过把master分支的位置移动到bugfix的最新分支上,Git 就会合并。这样的合并被称为fast-forward(快进)合并。

Git学习指南_第6张图片
合并后
说明GIT合并的两种方法以及区别。

答:Git代码合并有两种:Git Merge 和 Git ReBase

Git Merge:这种合并方式是将两个分支的历史合并到一起,现在的分支不会被更改,它会比对双方不同的文件缓存下来,生成一个commit,去push。

Git ReBase:这种合并方法通常被称为“衍合”。他是提交修改历史,比对双方的commit,然后找出不同的去缓存,然后去push,修改commit历史。

merge和rebase区别

如何查看文件的提交历史和分支的提交历史。

答:使用git log查看文件提交历史

Git log filename

使用git log查看分支提交历史

Git log branch file

当GIT出现如下情况时,该如何处理?

your-branch-is-ahead-of-origin-master-by-3-commits

答:
git commit -> git pull -> git push

提交代码注意事项

在提交项目之前必须先对项目进行更新,此项特别重要,如果不进行更新,别人有项目提交到服务器上,那么你的项目将会提交不上去,使用git解决冲突会比较麻烦,即使你解决了冲突,但是有时候不注意会冲掉别人写的代码,不像svn使用那么简单,所以提交自己项目前必须进行更新(特别重要);

git reset和git revert区别
  • git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。

  • 在回滚这一操作上看,效果差不多。但是在日后继续merge以前的老版本时有区别。因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现,但是git reset是之间把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入。

  • git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。

git log和git reflog区别

  • git log 命令可以显示所有提交过的版本信息
  • git reflog 可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作)

最佳实践

1. pull first

在修改代码之前,记得先执行git pull,把别人push的代码合并过来,这样可以避免一些无谓的冲突。

2. 小粒度commit,大粒度push

Commit的粒度要尽量适当的小,这对于cherry-pic或者代码回滚都非常有益。往远程push本地的提交的时候,粒度要尽量适当大些。这样其他的开发就不用频繁地去pull代码,同时代码回滚也非常方便。已经push到远程的提交,很多会影响提交历史的回滚操作都是不能进行的。比如,git reset,git commit -amend等等,否则会造成灾难。

3.合并分支时,适当适时使用--no-ff和--ff命令

分支管理要遵从git flow

你可能感兴趣的:(Git学习指南)