Note:本笔记是我学习廖雪峰老师的Git教程整理得到,在此向廖老师的无私付出表示衷心的感谢!

0、Git的历史

  • Git是一个分布式的版本控制系统(C语言编写,一开始为Linux社区服务,替代BitKeeper),方便自己管理版本的同时方便了团队协作
  • 分布式:每台终端上都有一个版本库,不依赖服务器(可选的服务器只是为了方便协作中的版本交换);集中式:依赖服务器工作,工作前下载最新版本,工作后上传自己的版本,没有服务器不能工作
  • GitHub是一个为开源项目提供Git存储的软件仓库,可以免费使用(前提是将托管的代码公开)
  • CVS和SVN是集中式版本控制系统,SVN是CVS的改进型
  • 其他版本控制系统:Microsoft Visual Studio的VSS,BitKeeper,IBM的ClearCase等

1、Git的安装

  • Mac要安装Command Line Tools,git工具在其中,Spotlight-Terminal-git-提示安装命令行工具,安装即可(也可以在Xcode-Preference-Downloads-Command Line Tools-Install安装)
  • Linux一般自带,不带则使用包管理器安装:
    • Debian系:sudo apt-get install git(or git-core,旧发行版中git指GNU Interactive Tools,后改名gnuit)
    • Red Hat系:sudo yum install git
    • Arch系:sudo pacman -S git
  • Windows要依靠Cygwin环境或WSL子系统,建议使用打包好的mysysgit

2、Git的几个重要概念

  • Git的几个区域:工作区 Working Directory - 暂存区 Stage/Index - 版本库Repository - 远程版本库(如GitHub)
  • Git管理的是修改,而不是文件
  • Git的HEAD是一个指针,指向当前分支的指针(比如说主分支master,而master指向主分支最新的提交),移动指针来改变分支和版本使得Git具有操作速度极快的特性
  • Git的每一个分支都有自己的工作区(受到git监视的目录)、暂存区以及版本库,在切换版本库的同时会同步切换
  • 标签是指向Commit号的指针,一旦建立不可移动;和Commit号一样标签具有唯一性

3、Git常用命令

  • git config 配置git基本信息(方便协作中识别身份,--global 表示全局,对所有没有单独设定的版本库均有效)及配置git工具参数

    • git config --global user.name "xxx" 设置全局用户名
    • git config --global user.email "xxx@xxx" 设置全局用户邮箱
    • git config --global color.ui true 打开全局下用不同颜色来区分不同的git提示的功能
    • git config --global alias.<alias> <command> 为命令设置全局别名,是为命令设置的别名,可以是任何文本(如带参数的命令)
  • git init 在当前目录启用git来监视版本并初始化git,产生.git隐藏目录,其中有本地版本库的各分支(Branches,默认有master分支)、HEAD指针和暂存区,不要删除

  • git add <filename> 将指定文件放入暂存区(没有提示表示成功),第一次add某一文件的同时会新增对其的监视(Track)

  • git commit -m "Commit messages" 将所有暂存区文件提交到版本库

    • Note:commit时使用 --allow-empty-message -m '' 参数可以不填写Commit messages而提交,但为了项目的可维护性极不推荐
  • git rm <filename> 用于在HEAD指向的版本库中删除某个文件,但注意需要 git commit 才能将更改提交至版本库

  • git status 查看受监视目录的状态(工作区文件相对于最新版本库是否有修改,暂存区是否有未Commit的文件等)

  • git diff <filename> 暂存区为空时比较当前工作区和最新版本库,暂存区不为空时比较当前工作区和暂存区,没有结果说明没有不同

    • Note:git diff加上 HEAD -- <filename> 参数则指定将当前工作区和最新版本库比较
    • Note:git只能显示文本文件的具体变化(二进制文件只知道变了没有),git diff的结构用Unix标准diff格式显示
    • Note:注意Windows记事本程序生成BOM头(0xEFBBBF)的问题
  • git log 查看版本库中存在的版本,每个版本包括一串SHA1计算得到的Commit号用于唯一标识改版本,此外还有版本的Commit messages,commit的日期、作者和作者的E-mail

    • Note:加入 --pretty=oneline 参数在一行内显示,更加紧凑
    • Note:加入 --abbrev-commit 参数可以将Commit号缩写为前几位显示
    • Note:加入 --graph 参数可以用图形画出分支情况,不需要自己看日志判断了(注意只有当其他分支被合并到当前分支,其他分支才会被显示)
    • Note:加入 -l 参数可以只显示最后一个Commit
  • git reflog (reference log) 显示自启用监视以来所有的版本操作记录(含Commit号),包括那些已经回退而不在 git log 中显示的版本

  • git reset 用于版本回退、版本回退后的强制还原和撤销暂存区修改(Unstage)

    • 版本回退:git reset --hard HEAD^(or HEAD^,etc.)(HEAD表示版本库最新版本,后面加几个就是向上回退几个版本)
    • 版本回退后的强制还原:git reset --hard <commit_id>,Commit号通过 git reflog 查询,可以简写为前几位(有区分性的)
    • 撤销向暂存区里add的某文件的修改并将其放回工作区:git reset HEAD <filename>
  • git checkout 用于撤销工作区的修改、(创建并)切换到新分支

    • git checkout -- <filename> 暂存区有此文件的修改,就将撤销工作区使其与暂存区一致(注意并不会同时撤销或者说是清空暂存区,撤销暂存区要使用 git reset HEAD <filename>);暂存区没有此文件的修改,就将撤销工作区使其与最新的版本库一致(想要回退旧的版本库,要使用 git reset --hard HEAD^(etc.) or git reset --hard <commit_id>

    • git checkout <name_of_branch> 切换到某分支

      Note:加入参数-b可以创建<name_of_branch> 分支的同时切换到该新分支

  • git branch 用于查看当前分支情况、创建新分支和删除分支

    • git branch 用于查看当前分支情况(当前分支用*标注)

    • git branch <name_of_branch>用于创建名为<name_of_branch>的新分支

    • git branch -d <name_of_branch> 用于删除<name_of_branch> 分支

      Note:当一个分支从未被合并就需要被删除时,需要使用-D参数替代-d参数以强制删除

    • git branch --set-upstream <name_of_branch> <name_of_remote_lib>/<name_of_remote_branch> 用于将本地库中未关联的<name_of_branch>分支与远程库<name_of_remote_lib>的<name_of_remote_branch> 分支建立关联,以方便使用简化命令git pull

  • git merge <name_of_branch> 用于自动合并<name_of_branch>分支到当前分支

  • git stash 用于将保存、恢复和删除当前工作现场(暂存区),在临时的Bug修复任务中十分有用(可以保护当前暂存区来不及Commit的修改)

    • git stash 将当前暂存区保存“入栈”并清空
    • git stash list 查看“堆栈”中保存的一个或多个工作现场
    • git stash apply 恢复最近一次保存的工作现场(不删除stash的内容)
    • git stash drop 删除最近一次stash的内容
    • git stash pop 将最近一次保存的工作现场弹出“堆栈”(删除stash的内容)
  • git remote 用于远程库的添加、查看操作

    • git remote add <name_of_remote_lib> git@server-name:path/repo-name.git 使用SSH协议为当前目录下的本地库关联一个远程库
    • git remote add <name_of_remote_lib> https://git.server-name/path/repo-name.git 使用HTTPS协议为当前目录下的本地库关联一个远程库
    • git remote 查看当前目录下本地库关联的远程库信息(默认只显示远程库名,添加-v参数显示包括地址在内的详细信息)
  • git clone <address> 克隆一个远程库的master分支到当前目录,

    可以是SSH格式的,也可以是HTTPS格式的网络地址

    Note:如果要克隆远程库的非master分支,需要使用先使用git clone 命令克隆master分支,再用git checkout -b <name_of_remote_branch> <name_of_remote_lib>/<neme_of_remote_branch>命令在本地新建<name_of_remote_lib>分支并将远程库<name_of_remote_lib>的<neme_of_remote_branch>分支同步到本地

  • git push <name_of_remote_lib> <name_of_local_branch> 将本地的<name_of_local_branch>分支推送到远程库<name_of_remote_lib>(添加-u参数将当前的<name_of_local_branch>和<name_of_remote_lib>设为缺省,之后可以使用git push的简化命令,当有其他分支的时候不建议简化命令)

    Note:git push命令也可以用来推送标签到远程(推送分支的同时不会推送标签),git push <name_of_remote_lib> <name_of_tag>推送单个标签到远程,git push <name_of_remote_lib> --tags推送本地所有标签到远程,git push <name_of_remote_lib> :refs/tags/<name_of_tag>从远程删除一个标签

  • git pull <name_of_remote_lib> <name_of_remote_branch> 从远程库<name_of_remote_lib>向本地拉取<name_of_remote_branch>分支的最新版本(git pull 省略参数的写法则会从关联的远程库中拉取当前所在的分支的最新版本)

  • git rebase 在利用git pull解决了git push出现的冲突后对本地分支“变基”,将合并后的Commit连接在拉取下来的Commit后而不是本地的Commit后,使得不再因为git pull解决冲突而产生新分支,最终推送到远程的分支结构更直接美观(HEAD -> master指示本地指针位置,origin/master指示远程版本库位置):

    • (解决冲突后使用git rebase

    • (解决冲突后使用git rebase

  • git tag 为Commit号打标签(-m参数同时为标签添加说明,-s参数同时为标签使用gpg即GnuPG工具签上私钥)、删除标签及查看所有标签,均为本地操作

    • git tag <name_of_tag> 在当前分支最新(HEAD指向的)版本处打一个名为<name_of_tag>的标签
    • git tag <name_of_tag> <commit_id> 为Commit号为<commit_id>的版本打一个名为<name_of_tag>的标签
    • git tag -d <name_of_tag> 删除名为<name_of_tag>的标签,不影响版本,只删除版本上面的标签
    • git tag 显示已经打好的所有标签名(按字母排序)
  • git show <name_of_tag> 显示标签名为<name_of_tag>的版本的信息

4、Git远程版本库的使用(GitHub/GitLab,etc.)

  • 开始使用远程版本库

    • Step1:自己注册一个GitHub账号(或联系你的管理员帮你创建一个GitLab账号)

    • Step2:在Terminal终端/Bash Shell/Git Shell(mysysgit)里用 ssh-keygen -t rsa -b <length_of_key> -C sth.(e.g.Your E-mail Address) 在~/.ssh目录下生成一对公私钥用于SSH认证,其中-C(Comment)参数不是必须的,id_rsa为私钥,妥善保存并防止显示出而泄漏,id_Rsa.pub是公钥

    • Step3:在GitHub的账户设置页面中"Add SSH Keys"中贴入id_Rsa.pub公钥中的全部内容(包含ssh-rsa前缀和最后你的Comment,完成基本配置

  • 将远程库与本地库关联

    • Step1:在GitHub上选“Create a new repo”建立一个远程库

    • Step2:在本地库中执行git remote add <name_of_remote_lib> git@server-name:path/repo-name.git 使用SSH协议关联一个远程库,远程库的名字通常取"origin"以体现其是远程库(命令示例:git remote add origin git@github.com:zjuyzj/LearnGit.git)

      (Note:使用HTTPS协议而不是SSH协议的地址也是可以的,如 https://git.server-name/path/repo-name.git ,只不过这样速度慢且每次都需要输入密码;git://地址默认使用SSH协议)

    • Step3:在本地库中执行git push <name_of_remote_lib> master将当前主分支推送到远程库(Note:git push命令添加-u参数后,此后再次推送可以省略origin master

  • 克隆一个现有的远程库到本地

    • 在终端内执行git clone git@server-name:path/repo-name.git即可将该远程库克隆到当前目录下
  • 从远程库拉取(git pull)提示“no tracking information”的原因和解决办法

    • 原因:本地当前分支未与远程分支建立关联(库是关联好的)(只有使用git clone命令得到的本地分支会自动与远程分支建立关联),且在git pull中没有指定<name_of_remote_lib>和<name_of_remote_branch>
    • 解决办法:使用git branch --set-upstream <name_of_branch> <name_of_remote_lib>/<name_of_remote_branch> 建立分支关联即可
  • 向远程库推送(git push)出现冲突的原因和解决办法

    • 原因:推送的内容和远程库上的内容存在git无法处理的冲突(对于文本文件,即修改内容在同一行上),一般是由于其他开发成员在你尚未推送的时候向远程推送了和你的修改有冲突的修改
    • 解决办法:先git pull拉回最新的远程版本库,此时会发生自动合并,出现合并冲突,手动修改冲突后Commit,最后再次尝试向远程库推送
  • 利用GitHub代码协作编辑的管理逻辑

    • 在他人的开源项目网页下点击“Fork”将该项目的各分支完整克隆到自己的账户下
    • 在自己的账户下对“Fork”的项目进行编辑修改(即在本地库和自己账户下“Fork”得到的远程库之间工作)
    • 在官方仓库的网页点击“Pull Request”,审核通过即可向官方仓库贡献代码

5、Git的分支管理

A、git merge <name_of_branch> 执行时可能发生的几种情况

  • 1、从产生分支开始,要合并的两个分支中一个做了修改,另一个没做修改,如:

合并时自动采用Fast-forward快进模式,master指针移动到dev处,完成合并(注意合并分支并不会删除被合并的分支,要删除请使用 git branch -d <name_of_branch>

合并后:

注意,以Fast-forward模式合并分支并删除被合并分支后,在git log里将不再能看出删掉的分支存在过的信息,而加入--no-ff -m "Infomation of merged branch" 参数后,会在合并时新建一个Commit号(以"Infomation of merged branch"为Commit message)作为合并后的版本,而不是直接移动指针来合并,即:

  • 2、产生分支后,两个分支都有修改,即:

  • 合并时两分支最新版本库上的修改不冲突(对于文本文件,即修改内容不在同一行上):

    合并时git会自动用vim打开一个说明文档,要求用户输入merge的理由(输入的内容不需要注释,git的提示会用#注释好以作区分),保存该说明文档后git自动合并两个分支上的修改(合并后的分支上的文件同时具有两分支各自的修改)

  • 合并时两分支最新版本库上的修改有冲突(对于文本文件,即修改内容在同一行上):

    合并时git会提示冲突(Conflict),使用 git status 可以看到有冲突存在(both modified),git会自动将发生冲突的文档中有冲突的部分标注在该文档中,用vim/cat等工具查看该文档可以看到,比如:

    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    Git tracks changes of files.
    <<<<<<< HEAD
    Creating a new branch is quick & simple.
    =======
    Creating a new branch is quick AND simple.
    >>>>>>> feature1

    其中,======= 为分割线,<<<<<<<>>>>>>>指明了分支的名字(HEAD为当前切换到的分支),之间夹的内容就是各个分支在同一行发生冲突的内容

    这种git无法自动处理的冲突需要手动解决,即对照git给出的冲突内容自行修改文档,得到一个自己认为总体满意的版本(定稿),对定稿进行git addgit commit后冲突解决,分支自动合并,git status里的冲突信息也会消失

    Note:冲突没有解决期间,不允许切换到待合并的分支!

B、开发时所应该采用的分支策略

  • master是极其稳定的分支,仅发布新版本使用,不轻易将其他分支合并到master分支;本地的master分支要时刻与远程同步以保持最新作为开发基础参考

  • dev是开发总分支,从master上产生,功能稳定后定期向master合并;本地的dev分支要时刻与远程同步以保证协作开发不出现严重冲突

  • 每个人都应该有自己的开发分支,从dev上产生,个人阶段性工作完成后向dev上合并

  • 需要修复某个分支上的Bug时,从该分支上产生新的Bug分支,在新分支上修复Bug,修复完成后向原分支合并并删除Bug分支即可;本地的bug分支一般都是临时性分支,不必向远程同步

  • 需要添加某实验性的功能时,从dev或master分支上产生feature分支,在feature分支上开发稳定后再合并并删除feature分支;如果需要合作开发新功能,本地的feature分支就需要向远程同步

6、.gitignore文件的使用

  • .gitignore是一个隐藏文件(以.开头),用来记录不被Git监控的文件名,这些文件不被Git监控(git status命令中不会列入"Untracked files...")
  • .gitignore文件中一行写一个文件名,允许使用通配符*
  • .gitignore文件放在被Git监视的目录下,也可以向远程同步,也允许对其进行版本管理
  • 不受监视的文件常常为:缩略图文件、编译产生的中间文件、个人敏感信息等

7、搭建一个私有Git服务器(简易代码仓库)

  • Step1:使用包管理器为Linux服务器安装git
  • Step2:新建一个系统用户,sudo adduser git
  • Step3:将所有用户的公钥导入到/home/git/.ssh/authorized_keys文件中,方便SSH登陆
  • Step3:初始化裸仓库(共享使用,没有工作区),选定一个目录,sudo git init --bare <lib_name>.git
  • Step4:更改仓库的属主和属组,sudo chown -R git:git <lib_name>.git
  • Step5:禁止git用户利用Shell登陆服务器,编辑/etc/passwd文件,将Shell从/usr/bin/bash改为/usr/bin/git-shell,这样从Shell登陆会引发自动退出
  • 之后用户就可以正常从服务器克隆<lib_name>.git仓库并推送了
  • 管理公钥的工具——Gitosis,管理权限的工具Gitolite(原生Git不支持权限管理)

【学习笔记】Git的日常使用的更多相关文章

  1. 学习笔记 - Git

    学习参考网址:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 Git是目前世界上 ...

  2. 学习笔记——git

    恩没错,又是个新东西 使用Git提交文件到版本库有两步: 第一步:是使用 git add 把文件添加进去,实际上就是把文件添加到暂存区. 第二步:使用git commit提交更改,实际上就是把暂存区的 ...

  3. Git学习笔记 git revert

    我们难免会因为种种原因执行一些错误的commit / push,git提供了revert命令帮助程序员修复这样的错误. 举个例子,下图是git commit 的历史记录 git revert 命令会通 ...

  4. 学习笔记--Git安装 创建版本库 图文详解

    一.Git下载 在Windows上安装git,一般为msysgit,官网地址:http://git-scm.com/ 我下载的是Git-1.9.2-preview20140411.exe 二.Git安 ...

  5. Git学习笔记--Git常用命令

    参考资料: http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 mkdir myfir ...

  6. python学习笔记——git的安装及使用

    1 git的基本介绍 git 是目前世界上最先进的分布式版本哦内阁制系统 详细信息可参考廖雪峰的官方网站中的Git教程 比git功能更加强大的有TortoiseGit和Tortoise SVN,具体安 ...

  7. Git 学习笔记--Git下的冲突解决

    冲突的产生 很多命令都可能出现冲突,但从根本上来讲,都是merge 和 patch(应用补丁)时产生冲突. 而rebase就是重新设置基准,然后应用补丁的过程,所以也会冲突. git pull会自动m ...

  8. Git 学习笔记--git 查看某个文件的修改历史

    1. git log -p filename 查看文件的每一个详细的历史修改,如果没有-p选项,只显示提交记录,不显示文件内容修改,git log -p -3 filename 显示最近的3次提交. ...

  9. git 学习笔记 Git实践

    网上有很多教程,这里我自己做下整理,省得有时忘记,有道是好记性不如烂博客! 先大概描述下Git的各种命令: git init                     #初始化 git clone   ...

  10. Git学习笔记 - Git安装

    Git安装(Windows) 从 https://git-for-windows.github.io/ 下载Git,下载完成,双击安装,一路选择默认设置即可. 注意:选择使用git的命令行模式,选择默 ...

随机推荐

  1. 五子棋C++版

    当前只完成了单机人人对战  后续会完成联机和AI的实现 定义棋盘 typedef struct { int kind; }Map; //棋盘 0为无子 1为黑子 2为白子 Map maps[line_ ...

  2. ELK学习实验009:安装kibana的仪表盘

    一 metricbeat仪表盘 1.1 安装metricbeat仪表盘 可以将metricbeat数据在kibana中展示 [root@node4 ~]# cd /usr/local/metricbe ...

  3. $CF888E\ Maximum\ Subsequence$ 搜索

    正解:$meet\ in\ the\ middle$ 解题报告: 传送门$QwQ$. 发现数据范围为$n\leq 35$,所以$2^{\frac{n}{2}}$是可做的. 所以先拆成$A,B$两个集合 ...

  4. 1044 火星数字 (20 分)C语言

    火星人是以 13 进制计数的: 地球人的 0 被火星人称为 tret. 地球人数字 1 到 12 的火星文分别为:jan, feb, mar, apr, may, jun, jly, aug, sep ...

  5. SCU 4439 Vertex Cover|最小点覆盖

    传送门 Vertex Cover frog has a graph with n vertices v(1),v(2),…,v(n)v(1),v(2),…,v(n) and m edges (v(a1 ...

  6. 比特币学习笔记(二)---在windows下调试比特币源码

    根据我一贯的学习经验,学习开源代码的话,单单看是不够的,必须一边看一边调试才能尽快理解,所以我们要想法搭建windows下bitcoin源码的调试环境. 紧接着昨天的进度,想要调试linux下的比特币 ...

  7. ArcGIS Server 动态图层发布调用图解

    目录 1 前言 1.1 简介 1.2 适用场景 2 动态图层 2.1 共享地图服务 2.2 动态工作空间添加 2.2.1 企业级数据库 2.2.2 shapefile文件夹 2.2.3 栅格文件夹 2 ...

  8. Linux之shell编程的基本使用

    1.Shell shell是一个命令行解释器,它为用户提供了一个向 Linux 内核发送请求以便运行程序的系统级程序 2.shell编程打印hello world 2.1 代码部分 #!/bin/ba ...

  9. js去除字符串的前后空白

    使用gravatar生成邮箱的头像时需要对邮箱地址哈希化,其中需要去除邮箱地址的首尾空白,查找了一些资料,总结一下 使用 js 提供的函数 trim() trim() 方法会删除一个字符串两端的空白字 ...

  10. 搭建自己的Online Judge

    前言 很多人对于做题有点厌烦,但是,如果让你出题给别人做那么可能会很有意思.可是,出题只能出在一些别人的OJ上,甚至只能在自己的Word文档里出.今天我教大家一个厉害点的,叫做搭建自己的Online ...