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@example.com(邮箱)"
这里简单的说明一下,加上--global
参数是表示配置的全局范围,针对所有的git项目而言的,当然也可以分别给某一个项目配置,进入到某个项目里面,去掉–-global
参数即可。
三、生成 SSHKey
Git推荐使用SSH协议传输文件(代码),会生成一个公钥和私钥,公钥配置在服务端,每次可以省去验证,方便快捷。当然使用https协议也是可以的,只不过是每次都需要输入用户名和密码,相对来说比较繁琐。
步骤:
任意空白处右键调出git Bash
命令控制台,如果是Mac系统,打开终端就行了,输入以下命令:
$ ssh-keygen -t rsa -C "youremail@example.com"
然后一路回车,使用默认值即可,应该是需要3个回车的,设置密码为空(注意按3个回车的时候别输入其他的,不然设置的密码不为空,你就等着每次提交输入密码吧)。如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_r sa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。一般这个id_rsa.pub里面的内容是要配到git服务器上面的(由统一的人去管理),然后我们就可以从服务器上面拿代码和提交代码了。Mac系统默认目录为~/.ssh
。
四、获取代码与提交代码
首先给大家介绍几个概念,一个是本地 worksapce 工作区,一个是 stash 暂存区,一个是 localRepository 本地库,一个是 remoteRepository 远程库。
- 从git服务器下载代码到本地
git clone git@github.com:ceeyang/ceeyang.github.io.git
- 查看本地分支和远程分支,其中
-a
参数查看远程分支
git branch
git branch -a
- 切换分支
git checkout dev
- 创建分支
git branch dev
- 删除分支(注意:删除分支需要先切换到其他的分支,如
master
分支,再执行删除操作)
git checkout master
git branch -d dev
- 创建分支并且切换分支
基于远程分支创建本地分支并且切换到该本地分支,基于远程 dev 分支在本地创建一个 dev 分支,并且切换到 dev 分支。
git checkout -b dev origin/dev
或者:
git checkout -b dev
- 暂存本地工作区的修改
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 username@www.dreamtech.com.cn: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这边可以这么做:
- 第一步,抓取远程库最新修改:
git fetch
- 第二步,指定某个文件进行更新:
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://xxx@www.dreamtech.com:12256/xxx
2.切换到对应分支:git checkout dev
、git 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 username@www.dreamtech.com.cn: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://xxx@www.dreamtech.com:12256/xxx
git push -u origin HEAD:refs/for/master
这里加了-u
参数,首次推送的话需要加上这个-u参数,以后都不需要了。