GIT

Git 快速入门教程

Posted by Cee Yang on June 25, 2017

Git 使用教程

一、Git 的安装

Windows版本 :

直接前往git官网下载msysgit安装包进行安装即可,安装流程和一般的windows软件的安装流程差不多,没什么区别。

Mac版本:

Mac已经自带了git,无需安装。

二、配置Git提交的用户名和邮件

这样做的目的是为了在git的log日志里面可以清楚的区分出每次的提交人是谁,以防日后出了问题能够立马清晰准确的定位出是哪个屌丝挖的坑,操作步骤:

打开 git 控制台:
  • Windows:随便在哪个空白位置右键,然后 git bash,调出git的命令控制台。
  • Mac:随便打开一个你喜欢的终端即可(Terminal, Iterm2 等)。
然后输入以下命令:
$ git config --global user.name "Your Name(用户名)"
$ git config --global user.email "[email protected](邮箱)"

这里简单的说明一下,加上--global参数是表示配置的全局范围,针对所有的git项目而言的,当然也可以分别给某一个项目配置,进入到某个项目里面,去掉–-global参数即可。

三、生成 SSHKey

Git推荐使用SSH协议传输文件(代码),会生成一个公钥和私钥,公钥配置在服务端,每次可以省去验证,方便快捷。当然使用https协议也是可以的,只不过是每次都需要输入用户名和密码,相对来说比较繁琐。

步骤:

任意空白处右键调出git Bash命令控制台,如果是Mac系统,打开终端就行了,输入以下命令:

$ ssh-keygen -t rsa -C "[email protected]"

然后一路回车,使用默认值即可,应该是需要3个回车的,设置密码为空(注意按3个回车的时候别输入其他的,不然设置的密码不为空,你就等着每次提交输入密码吧)。</br> 如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有 id_rsaid_rsa.pub 两个文件,这两个就是SSH Key的秘钥对,id_rsa 是私钥,不能泄露出去,id_rsa.pub 是公钥,可以放心地告诉任何人。</br> 一般这个 id_rsa.pub 里面的内容是要配到git服务器上面的(由统一的人去管理),然后我们就可以从服务器上面拿代码和提交代码了。Mac系统默认目录为~/.ssh

四、获取代码与提交代码

首先给大家介绍几个概念,一个是本地 worksapce 工作区,一个是 stash 暂存区,一个是 localRepository 本地库,一个是 remoteRepository 远程库。

  • 从git服务器下载代码到本地
    git clone [email protected]:ceeyang/ceeyang.github.io.git
    
  • 查看本地分支和远程分支,其中-a参数查看远程分支
    git branch
    git branch -a
    
  • 创建本地分支
    git brnach newBranch
    
  • 切换本地分支
    git checkout newBranch
    
  • 创建本地新分支并切换到该分支
    git checkout -b newBranch
    
  • 基于本地分支创建远程分支
    git push origin newBranch
    
  • 删除分支(注意:删除分支需要先切换到其他的分支,如master分支,再执行删除操作)
    git checkout master
    git branch -d dev
    
  • 创建分支并且切换分支 基于远程分支创建本地分支并且切换到该本地分支,基于远程 dev 分支在本地创建一个 dev 分支,并且切换到 dev 分支。
    // 1
    git checkout -b  newBranch origin/newBranch  
    // 2
    git checkout -b newBranch
    // 3
    git checkout newBranch
    
  • 暂存本地工作区的修改
    git add README.MD
    

    通常使用用(”.“代表所有文件,注意”.“前面的空格)

    git add .
    
  • 提交暂存区的内容到本地库中
    git commit -m "注释"
    
  • 抓取远程库最新提交的代码,
    git fetch origin dev
    

    或者:

    git fetch
    

    git fetch是简写(git 会自动搜索和当前分支名相同的远程分支名)

  • 将本地修改与远程进行合并此时,若遇到冲突,需要先手动解决冲突,再执行合并。
    git rebase origin/dev
    

这个时候如果出现了冲突,就先解决冲突,冲突解决完之后,需先缓存到本地工作区,然后执行合并。

git add .
git rebase --continue
  • 安装changeId自动生成hook   注意:如果使用了gerrit代码审查工具,提交的时候就必须要先生成这个changID值,如果没有这个changID,则不能到gerrit代码审核工具中进行代码审核操作了。而gerrit代码审查工具的存在就没有意义了。 操作步骤:进入到工作空间(workspace)中的仓库目录,输入如下命令:
    scp -p -P 29418 [email protected]:hooks/commit-msg .git/hooks/
    
  • 将本地仓库中的代码push推送到远程仓库中 这里需要注意: 我们也可以直接用命令git push origin dev将代码直接push到远程代码仓库,但是由于现在我们这边是使用了gerrit代码审查工具,所有不能直接这样推送,必须使用git push origin head:refs/for/dev 这个命令将代码推送到gerrit服务器上,然后我们再登录到gerrit中(会有一个web页面供我们操作)进行审核之后,执行最后合并,此时如果报错的话 有可能是因为你的changID没有生成,使用之前介绍的命令生成changID
    git push origin HEAD:refs/for/dev
    

    或者:

    git push origin head:refs/for/dev
    
  • 登录到gerrit服务器中,进行代码审核,然后执行合并(这一步先不管,专人统一审核,合并提交代码到远程中央仓库)

五、撤销修改

  • 场景一:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,使用
git checkout -- filename

通常用(”.”代表所有文件,注意”.”前面的空格)

git checkout -- .
  • 场景二:当你不但改乱了工作区的某个文件的内容,而且还提交到了暂存区(在本地执行了commit提交,但是还没有commit提交到远程服务器)时,想丢弃修改,分两步:

第一步: 使用命令:

git reset HEAD filename

或者使用.代替全部:

git reset HEAD .

就又回到了场景一.

第二步: 再按照场景一的步骤操作.

  • 场景三:已经提交了和不合适的修改带版本库时,想要撤销本次修改,则可以使用版本回退,但是前提是还没有推送push到远程库

版本回退见下面介绍

六、版本回退

HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令

git  reset  --soft commit_id

或者

git reset --soft HEAD^

穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。


七、Stash 暂存

关于git Stash的详细解释,适用场合,这里做一个说明: 当前工作区内容已被修改,但是并未完成。这时 Boss 来了,说前面的分支上面有一个 Bug ,需要立即修复。可是我又不想提交目前的修改,因为修改没有完成。但是,不提交的话,又没有办法checkout到另外的分支。此时用git Stash就相当于备份当前工作区了。然后在Checkout过去修改,就能够达到保存当前工作区,并及时恢复的作用。 之后,另一个版本的 bug 修复完毕之后,再使用checkout切换回之前的分支,然后再使用git stash pop命令或者git stash apply命令就又可以恢复回来了。

git stash save "备注说明"

备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。

git stash pop stashId

从Git栈中读取最近一次保存的内容,恢复工作区的相关内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复。

git stash list

显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。

git stash clear

清空Git栈。此时使用gitg等图形化工具会发现,原来stash的哪些节点都消失了。

八、git如何放弃所有本地修改

git checkout .

放弃本地所有修改的。没有的提交的,都返回到原来的状态 

git stash .

把所有没有提交的修改暂存到stash里面。可用git stash pop恢复。 

git reset --hard HASH

返回到某个节点,不保留修改。

git reset --soft HASH

返回到某个节点。保留修改

九、Git只更新远程库中的单个或者指定的文件

在开发过程中,我们有的时候并不需要更新远程所有的文件,而只需要更新某一个或者说特定的文件,如何操作呢? SVN 更新单个文件只需要svn up file/to/updat,非常简单,而且没有任何歧义。 但是git由于在远程服务器和本地都有一个代码库,这样只更新单个文件的话比SVN稍微要麻烦一点。

  • 如果想拿远程git服务器上的最新版本(或者某个特定版本)去覆盖本地的修改,可以使用git pull命令,但是这样会全面更新本地代码库和工作拷贝。
  • 如果想放弃本地工作拷贝所做的修改,可以使用 git checkout filePath命令,但该命令只能用本地库覆盖你的工作拷贝,并不能取得远程版本的更新。 所以,正确的方法应该是先更新本地库(但是不更新工作拷贝),然后用本地库来更新单个的工作拷贝文件。

例如:假设说开发小伙A在本地新增或者是修改了某个文件file1,然后提交到远程库了,之后开发小伙B想要拿到这个file1文件,(注意场景:这里是只想拿到这一个文件file1,小伙A有可能提交了多个文件),那么小伙B这边可以这么做:

  1. 第一步,抓取远程库最新修改:git fetch
  2. 第二步,指定某个文件进行更新: git checkout origin/dev -- filePath

十、分支的合并

假设我们当前的版本有一个master主干分支,同时还有一个dev开发分支,因为通常情况下我们做开发都是在dev分支下进行的开发,之后开发完成后需要将dev分支开发的功能同步到master主干分支上,也就是合并到master分支上,那么怎么操作呢?

1.首先切换到需要合并的分支上,打个比方说:现在我们需要将dev分支合并到master主干分支,第一步:首先我们需要切换到master主干分支上 :

git checkout master

2.为了保证当前的本地master分支的内容与远程服务器中master分支的内容保持同步,我们需要先同步代码:

git pull origin master

通常我们会拆成两个步骤来完成:

git fetch origin master

或者

git fetch
git rebase origin/master

3.将dev分支合并到当前master分支

git merge dev

或者

git merge --no-ff dev

4.此时如果在合并的过程中出现了冲突,则需要先解决冲突,解决方法同 svn 差不多

5.冲突解决完之后,再继续执行合并操作

git add -A
git rebase --continue

6.合并成功之后,我们再将master分支push推送到远程库中即可

git push origin master

十一、如何合并某个分支中的一个或者是几个commit(s)提交

git cherry-pick可以选择某一个分支中的一个或者是几个commit(s)来进行合并操作。在实际应用中,我们可能会遇到这样的情况:

假设现在我们有个稳定版本的分支叫做release,另外还有一个开发版本的分支叫做dev,然后我们在dev开发分支里面修改了一些东西(新增了几个个功能,或者是修复了几个bug等等),之后 commit 了几个(这里注意是几个)更新操作(也就是提交到了本地库),但是后来我们发现同样需要在release分支上同步应用某个更新,我们不能直接将release分支和dev分支执行合并,因为这样将会导致稳定版本混乱,但是确实又想增加一个dev分支中的某个功能到release分支中来,那么这时我们就可以使用cherry-pick命令来解决这个问题了,就是对已经存在的commit进行再次commit(提交)操作。简单用法:

git cherry-pick <commit_id>

注意:当执行完cherry-pick以后,将会生成一个新的提交,这个新的提交的哈希值和原来的不一致,但标识名是一样的。

1.首先,切换到dev开发分支

git checkout dev

2.然后找到dev分支的commitId 38361a6(说明:本来commitId是38361a68138140827b31b72f8bbfd88b3705d77a这么多位,但是可以只取前7位就行了。使用git log命令可以查看提交的 commitId

git log
commit 38361a68138140827b31b72f8bbfd88b3705d77a

3.之后再次切换回 release 分支

git checkout release

4.更新一下 release 版本的代码,保持与远程仓库的同步

git fetch origin release
git rebase orgin/release

5.执行cherry-pick命令,同步 dev 分支的修改代码

git cherry-pick 38361a6

6.如果顺利,就会出现下面这段提示,当然也有可能不出现这段提示,只要没报冲突,则说明代码同步成功了。

Finished one cherry-pick
# On branch old_cc
# Your branch is ahead of 'origin/old_cc' by 3 commits.

7.如果在cherry-pick的过程中出现了冲突就手动解决冲突,解决完冲突之后根据提示继续执行同步。

git add -A 
git cherry-pick --continue

8.最后push到远程仓库。

git push origin release

十二、一个完整的团队开发流程

1.克隆远程仓库

git clone ssh://[email protected]:12256/xxx

2.切换到对应分支:git checkout devgit checkout -b dev or git checkout -b dev origin/dev

git checkout -b dev origin/dev

3.查看当前分支状态,查看提交。

git status
git log

4.添加 commit msg ,一个项目只需要添加一次即可。

scp -p -P 29418 [email protected]:hooks/commit-msg .git/hooks/

5.当本地修改后,缓存本地文件。添加 commit msg。

git add -A 或者 git add .
git commit -m "注释"

6.抓取远程提交,合并本地代码。

git fetch origin dev
git rebase origin/dev

这个时候如果出现冲突,注意出现冲突只可能会是在合并(rebase)时出现冲突,那我们就直接解决冲突即可,解决完之后,再依次执行:

git add -A
git rebase --continue

9.推送到远程仓库。

git push origin HEAD:refs/for/dev

或者如果远程库(gerrit仓库)只是一个空的仓库的话,这就需要先将本地库的代码关联到gerrit远程库(即将本地库与远程库建立映射关系),之后再推送上去。执行以下命令:

git remote add origin ssh://[email protected]:12256/xxx
git push -u origin HEAD:refs/for/master

这里加了-u参数,首次推送的话需要加上这个-u参数,以后都不需要了。