Zrocky

Stay Hungry, Stay Foolish

Think Different


欢迎与我交流

使用Git进行版本控制

公司一直在使用SVN来做版本控制,虽然个人项目早已换成Git,但是对Git没有一个深入的了解,最近因为分支和标签用法的困惑,继而产生想系统学习Git使用的想法,本文是基于廖雪峰Git教程而整理的学习笔记。

Git概念

版本库和工作区

版本库和工作区

master是Git自动创建的第一个分支

Git工作分为两步

  1. git add把文件修改添加到暂存区 git add
  2. git commit把暂存区的所有内容提交到当前分支 git commit

Git协议

Git支持多种协议,git://https等,https协议速度会慢一些

专有名词

mastergit自动创建的第一个分支

HEAD当前版本

origin远程库

基础命令

  1. 在目录中初始化Git

     git init
    
  2. 将修改添加到Git

     # 添加全部改动(常用)
     git add .
    
     # 添加具体变动
     git add file1 file2
    
  3. 将修改提交

     git commit -m "changelog"
    
  4. 查看仓库当前状态

     git status
    
  5. 查看文件修改内容

     git diff filename
    
  6. 查看Git日志

     # 完整日志(带时间)
     git log
        
     #精简日志
     git log --pretty=oneline
    
  7. 将当前版本回退(切换)到具体版本

     # 回退到具体版本号(版本号不需要写全,只需前几位)
     git reset --hard commit_id
        
     # 回退到当前版本的上一版本
     git reset --hard HEAD^
    

HEAD表示当前版本 上一个版本就是HEAD\^ 上上一个版本就是HEAD\^\^ 当然往上100个版本写100个\^比较容易数不过来,所以写成HEAD~100

  1. 查看历史命令(历史版本号)

     git reflog
    
  2. 撤销工作区中的修改(使用版本库中的版本替换工作区版本)

     # “--”很重要,不然会和checkout命令冲突
     git checkout -- filename
    
  1. 一种是file自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
  2. 一种是file已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
  1. 撤销暂存区中的修改

    git reset HEAD filename
    
  2. 将本地仓库添加到远程库中

    git remote add origin [email protected]:zrocky/testgit.git
    
  3. 将本地库中的内容推送到远程库上

    # 首次push需添加-u参数
    git push -u origin master
        
    # 提交到远程库
    git push origin master
    

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来

  1. 从远程库中克隆到本地库

    git clone [email protected]:zrocky/testgit.git
    

分支与标签

Branch(分支)

master为主分支

HEAD指向当前分支

每次提交master分支都会向前移动一步

创建新的分支dev,将HEAD指向dev

从现在开始,工作区的修改和提交就是针对dev分支的了

假如我们在dev上的工作完成了,就可以把dev合并到master

合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支

过程动画:

分支命令

  1. 创建分支

     git branch dev
        
     # 创建并切换分支
     git checkout -b dev
    
  2. 切换分支

     git checkout dev
    
  3. 查看当前分支

     git branch
    
  4. 合并分支到当前分支

     git merge dev
    
  5. 删除分支

     git branch -d dev
    
  6. 查看分支合并图

     git log --graph
        
     # 显示简化图
     git log --graph --pretty=oneline --abbrev-commit
    

分支合并冲突

此种情况需解决冲突再提交

分支策略

如果分支合并没有冲突等异常情况,Git会使用Fast forward(快进)模式,该模式下,删除分支后,会丢失分支信息

使用--no--ff参数禁用Fast forward:

git merge --no-ff -m "merge with no-ff" dev

分支开发策略

master分支是非常稳定的,也就是仅用来发布新版本,平时不在上面工作,开发都在dev分支上,每个人再有自己的分支,按时向dev分支合并即可,团队合作的分支看起来是这样的

bug处理分支

dev分支工作,手头工作并未完成,不能提交,但是bug急修,这个时候,可以使用stash先将工作区暂时“储藏”起来,等修复bug后再恢复

git stash

假定为修复线上bug,可从master分支创建临时分支

git checkout -b issus-101

bug修复完成后,合并分支到master,再切换回dev分支,使用stash恢复之前的工作区

查看stash挂起的任务

git stash list

恢复stash任务

# 只恢复任务,挂起的任务还在list中
git stash apply [email protected]{0}

# 恢复的同时把stash挂起任务删除
git stash pop

删除stash list中任务

git stash drop [email protected]{0}
Feature分支

feature分支和bug分支的处理类似,但如果feature最终放弃,需要删除分支时,使用原来的分支将会报错,需要删除未合并的分支时,要使用-D参数强行删除

git branch -D feature-vulcan
多人协作

查看远程库信息

git remote

# 详细信息
git remote -v

推送分支到远程库

# 主分支
git push origin master

# 开发分支
git push origin dev

  1. master分支为主分支,需要时刻与远程同步
  2. dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步
  3. bug和feature则按需求决定是否同步到远程
抓取分支

从远程库clone到本地时,默认只能看到master分支,如果需要再dev等其它分支上开发,则必须创建origin远程库的dev分支到本地

git checkout -b dev origin/dev

如果push更新到远程分支时发生冲突,则需要使用git pull命令从远程拉取更新,在本地处理完冲突后,再用git push origin <branch-name>命令push到远程库

如果git pull命令提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>解决

Rebase(变基)

使用rebase可以整理本地commit的分叉,使之变成线性,而不再是“蜘蛛网”,rebase只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作

git rebase

Tag (标签)

tag是版本库的一个快照,和branch相似,但是不能像branch一样移动

基于当前分支创建新标签

git tag v1.0

基于特定版本创建新标签

git tag v0.9 f52c633

# 指定说明文字
git tag -a v0.1 -m "version 0.1 released" 1094adb

查看所有标签

git tag 

查看某个标签的信息

git show v0.9

推送标签到远程库

git push origin v1.0

推送全部标签到远程库

git push origin --tags

删除本地标签

git tag -d v0.1

删除远程标签

# 先在本地删除
git tag -d v0.9

# 远程删除
git push origin :refs/tags/v0.9

Git高级

远程库操作

删除远程库

git remote rm origin

只删除了关联关系,并未删除远程数据

添加多个远程库

git remote add bitbucket [email protected]:Zrocky/git_test.git

只需在push时,选择相应的远程库即可

修改远程库名称

git remote rename oldname newname

忽略文件

有一些文件你不想上传至git仓库中,这个时候可以使用忽略功能,将需要忽略的文件标示给git。

首先在Git工作区的根目录创建一个.gitignore文件,把需要忽略的文件名填写进去,git就会自动忽略这些文件。GitHub创建了一些可供参考的预设文件,我们可以直接拿来修改使用:gitignore

忽略文件的原则是:

  1. 忽略操作系统自动生成的文件,比如缩略图等;
  2. 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
  3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

搭建Git服务器

搭建Git服务器,需要准备一台运行Linux的机器,推荐使用Ubuntu或Debian

第一步,安装git

sudo apt-get install git

第二步,创建一个git用户,用来运行git服务:

sudo adduser git

第三步,创建证书登录

收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。

第四部,初始化Git仓库

sudo git init --bare sample.git

Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:

sudo chown -R git:git sample.git

第五步,禁用shell登录

出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:

git:x:1001:1001:,,,:/home/git:/bin/bash

改为

git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell

第六步,克隆远程仓库

git clone [email protected]:/srv/sample.git 

管理公钥

如果团队成员比较多,可以使用Gitosis管理公钥

管理权限

Git本身不支持权限控制,不过Git支持hook,所有可以在服务器端编写脚本实现权限控制,使用Gitolite可以实现这个功能

最近的文章

首例免疫艾滋病基因编辑婴儿

351年前的冬天,一位法国医生完成了一例给人输血的手术,用的是牛血。 病人死了。 这个医生名叫让-巴蒂斯特·德尼。此前他已经给两人输了一点羊羔的血,两人都活了下来。大受鼓舞的德尼从巴黎的街上绑架了一个疯子,拿绳子捆起来强迫他接受输血“治疗”,不料这个疯子出现了明显的不良反应;德尼不肯放弃,第三次输血之后疯子死了。 事情闹上了法庭。出乎众人意料的是,德尼没有因为杀人而上绞刑架。法庭发现这个疯子并非死于输血,而是死于砷中毒。 德尼自己不可能给患者下毒,患者死了实验就失败了,肯定另有...…

Social继续阅读
更早的文章

使用fastlane自动部署iOS App

fastlane是为iOS和Android应用程序自动执行beta部署和发布的最简单方法。它处理所有繁琐的任务,例如生成屏幕截图,处理代码签名和发布应用程序。基本使用安装fastlane 安装最新的Xcode命令行工具 xcode-select --install 安装fastlane(可以使用RubyGems或Homebrew安装) # Using RubyGems sudo gem install fastlane -NV # A...…

Fastlane继续阅读