Git用法的全面解析,结合Android Studio来讲Git

今日快讯

今天凌晨1点钟,万众期待的苹果新品发布会终于召开了。由于今年是iPhone问世的十周年,因此这个十周年纪念版的iPhone也是备受瞩目。这次的发布会上,苹果推出了Apple Watch 3、Apple TV 4k、iPhone 8、iPhone 8 Plus以及iPhone X这几款产品。其中iPhone 8和iPhone 8 Plus较为鸡肋,虽然名字是叫8,但是和iPhone 7在外观上没有任何区别,连之前爆料的竖排双摄像头也都没能实现,仍然保持的是7时代的横排双摄像头,仅仅只有一些硬件上的提升。因此这两款设备应该说是名义上的8,实质上的7s。售价方面比较中规中矩,iPhone 8 5888元起售,iPhone 8 Plus 6688元起售。

而苹果这次发布会的压轴产品iPhone X才是重头戏,X是罗马数字10的意思,也意味着10周年纪念版。iPhone X是苹果历史上首个使用全面屏的手机,取消了Home键,取消了Touch ID,改用Face ID来解锁手机。为了实现全面屏,iPhone X不得不采用了刘海式的设计,有人觉得很丑,但也有人觉得好看,萝卜白菜各有所爱嘛。iPhone X采用了竖排双摄像头,虽然我也不知道竖排比横排优越在哪里,但是毕竟与众不同才更有逼格。售价方面,iPhone X分为64GB和256GB两个版本,其中64GB售价8388元,256GB售价9688元,这也是苹果历史上最贵的手机了,再加上黄牛一炒,分分钟上万有木有。

这样的iPhone你会不会考虑买一部呢?不管你买不买,我反正肯定是买不起 

作者简介

本篇来自 KUMATIC 的投稿,分享了 git 和 Android Studio 有效结合相关的内容,希望大家喜欢!

KUMATIC 的博客地址:

http://blog.csdn.net/sxh951026

Git 简介

版本控制系统的作用

版本控制系统的功能主要有三个。

  1. 备份代码。很常见的,今天的工作做完了,提交一下,明天改了改,发现还没昨天的好,使用 Git 的话,直接回退到上一个版本即可,再也不需要手动分日期保存代码了。爱玩游戏的同学,可以发现这和游戏里的存档功能很像。

  2. 在多人合作开发时,同步并合并对代码的修改。多个人开发的时候,小明开发了一个功能,小红开发了一个功能,他们需要把各自的功能合并到一起。于是小明先要把自己的代码发给小红,小红把自己要的代码挑出来,合并到自己的代码里(合并的过程真的很麻烦),然后把整个代码再发回给小明,然后继续开发。上述操作通过Git的指令可以自动完成,十分简便。

  3. 方便项目开发的管理。比如说,在开发下一个版本的同时,可以在前一个版本的基础上修复 bug,使用Git可以使这两个工作互不干扰。再比如说,软件出 bug 了,通过 Git可以诊断出是谁在哪次提交上引入了这个 bug,方便分锅哇。

注意一下,并不是只能管理代码,word 文档,图片,设计稿之类的东西都是可以管理的。

Git 的诞生

Git 是在 Linux 内核开源项目的维护工作中诞生的,于2005年。父亲是 Linux 之父 Linus  Torvalds,从亲缘关系上讲,Git 是 Linux 的弟弟。

那个时候的情况是这个样子的!因为 Linux 是一款自由软件(具体什么是自由软件,请出门百度),开源,免费,而且谁都可以参与项目开发,所以吸引了一大批牛掰的程序员,他们修改 Linux 源码,将自己的代码发给 Linus,再由 Linus 将代码合并到 Linux 内核中去。由于参与者非常多,代码的维护非常繁琐。所以在2002年的时候,启用了一个叫做BitKeeper的分布式版本控制系统。

BitKeeper 是一个商业软件,是付费的,不过出于人道主义精神,BitKeeper 所属的公司授予了 Linux 社区免费使用 BitKeeper 的权限。但是在2005年的时候,由于Andrew Tridgell(Samba的开发者)违反 BitKeeper 的使用原则,对 BitKeeper 开始进行逆向工程,使 Linux 社区失去了免费使用 BitKeeper 的权限。

然后重点来了,Linus 在失去 BitKeeper 的支持后,根据他对 BitKeeper 的理解,并综合了当时版本控制系统的一些缺陷,花了一两个星期,用 C 语言写出了Git!

Git 配置和仓库初始化

下面是会介绍 Git 的使用,每个小节里会讲解各个功能在命令行中的实现方式,并在每小节的最后介绍在 Android Studio 中的图形界面里怎么使用对应的功能。

Git 配置

在安装完 Git 后,会有一个叫做 Git Bash 的程序,打开之后会出现一个跟 Linux 命令行操作界面神似的命令行窗口,其中可以输入各种Git指令和一些 Linux 指令。

在使用 Git 之前,需要进行一步设置,在命令行中输入:

这两条指令就相当于给自己的电脑取了个名字。在之后的每次提交(备份)中,这两个属性都会被添加到那一次提交生成的提交对象中。在协同开发时,大家可以通过这个名字来区分是谁完成了这个功能,是谁写出了那个 Bug。

当然 Git 中可以进行的设置还有很多,有兴趣的可以查阅 git config 这个命令。另外,--global 这个参数表示电脑上的所有仓库都会使用这个名字,当然你也可以给每个仓库指定不同的用户名和 Email 地址。

在 Android Studio 中使用 Git 还需进行如下配置。 

在 Android Studio 中使用 Git 需要将安装完成的 Git.exe 文件配置到 Android Stdudio 中。具体步骤如下,首先点击 File->Settings 打开 Settings 对话框,接着点击 Version Control->Git 进入相应目录,在 Path to Git executable 中填入 Git.exe 所在位置。

之后点击Test进行测试,如果弹出成功信息,则配置完成。

创建 Git 仓库

在 Git 中,创建 Git 仓库对应的指令为 git init,它会把当前目录初始化为一个 Git 仓库。使用命令行的话,你可以先把 Android 工程建好,再是一顿 cd 和 mkdir 和 ls 来到相应的目录,执行 git init 来初始化仓库,也可以先建立好仓库,再把工程建在里面,没毛病!

如果用 Android Studio 初始化仓库。 

首先新建一个工程。再点击 VCS->Create Git Repository,会弹出一个对话框,让你选择Git 仓库的初始化目录,一般都会选择工程的根目录。

注意: 其实在 Android Studio 中也可以打命令行,在底部的 Terminal 栏目里输入命令即可。但是因为各种别扭,打命令行还是喜欢用 Git bash。

点击 OK 即可完成仓库的创建。 在新建Git仓库之后,会发现 Android Studio 底下多出了一个 Version Control 栏目。在其中可以进行许多方便的 Git 操作,包括分支的图形化显示,文件状态的浏览等。细心的同学应该会发现其中的文件是红色的,这里的颜色表示了文件的状态——文件还没有被加入到暂存区中(后面会具体讲暂存区)。

用 Git 备份代码

我们通常是这么备份代码的。第一步,在上一个备份点继续开发。第二步,在想要备份的时候,打个包,存到电脑上,如果怕电脑中病毒瘫痪之类的,可能还会发一份到云盘上,第三步,继续在这一个备份点上开发,……。在开发中,考虑到包的大小和一些自动生成的配置文件和编译过程中产生的文件等,会在上述步骤中再添加一步。即在备份之前,把需要的改动挑选出来,再进行备份。

Git 备份代码,其实也就是这三步。

  1. 在上一个版本的基础上继续开发,修改代码。

  2. 用 git add 指令,将需要的改动添加到暂存区(顾名思义,一个暂存文件的区域),对应上面的挑选改动操作。

  3. 用 git commit 指令,将暂存区中的改动与上一个提交(备份)结合,形成一个新的提交(备份),对应上述操作中的备份操作。

注意:这里的改动并不单单指对原文件的修改,也包括创建文件,删除文件。

在本地备份代码

在 Git 中用 git add 和 git rm 操作来添加改动到暂存区,并用 git commit 来生成一个提交(备份)。接下来分别介绍添加文件,修改,删除这三种改动的添加到暂存区的和提交的方法。

关于暂存区到底是个什么东西。 
我们把平时看到的电脑上的目录叫做工作区,里面是我们实际操作的文件。而暂存里面一开始会包含上个提交时的所有文件,然后我们会通过 git add 和 git rm 操作来把工作区里的改动添加到暂存区,比如添加新文件到暂存区,把修改后的文件添加到暂存区以及删除暂存区中的文件。当最后提交时,Git 把暂存区中的所有文件组织成一棵树,再加入时间,作者等信息形成一个 commit 对象,再把 commit 对象与上一次提交生成的 commit 对象连接起来,就完成了一次新的提交。(上述表述不是非常严谨额,大家别太较真,意思懂了就行。Git 管理文件的方式与 Unix 的文件系统类似,想具体了解可以去看 Git 官网的教程)

在新创建 Git 仓库后,所有文件都还没有加入到版本控制系统中,当前仓库是空的。这里有的同学就奇怪了???你不是用git init在这个目录下初始化了 Git 仓库吗,我这个目录下好多文件呢,你怎么说他是空的呢。!!!注意,当前目录下的文件并不属于 Git 仓库!!!在 git init 之后,会在当前目录下生成一个.git目录(在windows里这个目录隐藏的,设置了显示隐藏文件之后可以看到),里面有一个objects目录,这个目录下的文件才是属于Git仓库的。刚初始化的仓库的objects目录就像下面这样,有两个目录,一个info,一个pack,不过里面啥也没有,都是空的。

这时,对于 Git 来说,存在了许多新建文件。在命令行中输入 git status 可以查看仓库的状态,其中的 Untracked files 中的内容,就是我们还未添加的改动——添加文件。

  • 改动类型一:添加文件

在上面的 git status 中显示的 untracked files 均是在当前版本中还未添加到暂存区里的文件。可以用 git add <file> 来将他们加入暂存区。在加入之后用 git status 查看仓库的状态。

会发现,多了一段提示,Changes to be committed(等待提交的改动),其中显示的就是new file(新文件)。这说明,我们已经将需要的改动添加到暂存区了。这个时候再去查看 .git\objects 目录,会发现多了一个文件。

添加完成后用 git commit -m "提交信息"将暂存区中的内容生成一个提交(备份)。

用 git log 指令可以查看当前的提交历史。可以看到多了一个提交,提交信息就是我们刚才输入的添加了 MainActivity。从这里也可以看到,在第一步 Git 配置时,设置的用户名和邮箱都自动添加到了提交信息中。

  • 改动类型二:删除文件

在我们删除文件后,可以通过 git rm <file> 来把暂存区中的文件也给删掉,从而将改动更新到暂存区。在我们的第一个版本中,我们添加了一个新的文件 MainActivity.java,下面我们把它删除,并添加另一个 activity_main.xml 文件(为了方便修改操作的演示)。

在把工作区中的 MainActivity.java 删除了,运行 git status,Git会很机智的告诉我们 MainActivity.java 已经被删除了,但还没有更新到暂存区。

我们用 git rm <file> 将对 MainActivity.java 的改动更新到暂存区,并添加 activity_main.xml 到暂存区里。

执行完成后,用 git status 查看仓库状态。可以看到 Changes to be commited 里有了 deleted 和 new file 两条改动信息。

最后提交一下修改。再用 git log 查看一下提交历史。

提交历史如下,又生成了一个提交了哈。

  • 改动类型三:修改文件

在我们修改了文件之后,将修改更新到暂存区的操作也是 git add <file>,这里可能有同学会觉得奇怪,为什么修改文件也用 git add,add 不是添加文件的意思吗,其实从本质上讲 Git 对已修改文件的处理方式就是将修改后的文件整个加入到暂存区替换掉原文件,那用 add 更新修改也就顺理成章了。

现在我们的我在 activity_main.xml 的最后加一行 modifyTest,运行 git status 会有下面的 modified 提示。

我们用 git add <file> 来把修改添加到暂存区,然后查看仓库状态。

最后提交一下修改。再用 git log 查看一下提交历史。

提交历史如下,又生成了一个提交了哈。

  • 更新所有内容到暂存区并提交

大部分的时候,我们会把所有的改动都更新到缓存区并提交,可以使用 git commit -am  "提交信息",它会自动把所有已经跟踪过的文件暂存起来一并提交,包括修改和删除,他是 git add -u 和 git commit -m "提交信息"的结合。如果要把全部文件的添加,修改,删除三种改动全部添加到暂存区去,可以用 git add -A。

通常我们还需要忽略一些指定的文件,比如在 java 编译后生成的 .class 文件等,这可以通过 .gitignore 文件来完成。具体见 .gitignore 的使用这一节。

至此,添加三种改动到暂存区的方式就讲完了,大家可以组合这三种操作完成各种各样的任务!

  • git status 原理

在用 git status 查看仓库状态是,经常会看到 Untracked files,Changes not staged for commit 和 Changes to be committed 三个标题。大家大概能知道里面的内容是什么意思,但有时还是会感到迷惑。接下来我们会介绍这三个标题下内容的由来。

这三个标题中的内容是根据三个文件树产生的。这三个文件树分别为工作区,暂存区和上一个提交中的文件区(仓库刚初始化的时候,没有提交,相当于文件树为空)。Untracked files 显示的是工作区中存在而暂存区中没有的文件,通常为新建的文件,而 Changes not staged for commit 里是工作区中和暂存区中内容不同的文件,通常是因为修改了文件,显示为 modified,以及暂存区里存在但工作区里没有的文件,通常是因为删除了文件,显示为 deleted 。而 Changes to be committed 里显示的是暂存区里有,但是上一次提交中没有的内容。

Android Studio 中的相应操作 

先切换到 Version Control 栏目的子栏目 local Changes 中,在这里可以看到修改的文件。在里面会看到两个目录,一个是 Defult,一个是 Unversioned Files。前者中显示的是未添加到暂存区的文件,后者中显示的是未添加到暂存区的文件。

相比命令行的方式,图形界面有更方便的方法来生成一个提交。用户可以直接勾选所需添加的改动,然后直接提交。(Git 会有一个暂存区的存在,其中一个原因就是为了模拟挑选改动的行为)。在 Android Studio 中,点击图中框出的按钮会弹出 Commit Changes 对话框,来进行提交操作。

之后可以在弹出的窗口中,选择要更新到暂存区的文件,填写提交信息,完成后就按下提交即可完成。

在 Version Control 的 Log 子栏目下可以已图形化的方式查看提交历史,其中 HEAD 标志了当前所处的版本,master 标志了 master 分支的位置。

撤销修改

撤销修改有关的命令主要就是两个,git checkout -- <file> 和 git reset HEAD <file>,关于这两个命令,主要记住两点。

  • git checkout -- <file> 是把工作目录下的文件用暂存区里的文件代替

  • git reset HEAD <file> 是把暂存区里的文件用上一次提交时的文件代替。

先看一个例子来了解他们的区别。在上一次修改 activity_main.xml 后,这个文件内容如下:

我们把最后一行 modifyTest 删掉,先不更新修改到暂存区,然后执行以下指令

$ git checkout -- app/src/main/res/layout/activity_main.xml

再回到 activity_main.xml 中,会发现删除的内容又回来了。

这次我们再把最后一行 modifyTest 删掉,执行以下指令,将修改更新到暂存区再执行 git checkout。

再回到 activity_main.xml 中,会发现删除的内容并没有回来。

为什么呢?因为 git checkout -- <file> 撤销修改是把暂存区对应的文件替换工作目录下的文件,所以没有更新到暂存区的修改可以撤销,而更新到暂存区的修改不能撤销。

如果要取消添加到暂存区的修改可以采用 git reset <file>,这个命令可以撤销暂存区里对应文件的修改,但工作目录中的文件不会改变,因为这个命令是用上一次提交中的文件替换暂存区的文件。如果想把工作目录和暂存区中的文件都恢复到上次提交时的样子,可以用 git reset <file> 再 git checkout <file>。

在工作中,如果你的工作还没有添加到暂存区,那么用 git checkout <file>即可,如果添加到了暂存区,想要恢复,可以先 git reset <file> 再 git checkout <file>。

Android Studio 中的相应操作 

在 Android Studio 中撤销修改非常简单,在 Version Control 中选中要撤销修改的文件,鼠标右键,在弹出的菜单中选择 Revert 即可撤销修改,注意这边的撤销修改是恢复到上次提交时的样子,相当于使用 git reset <file>和 git checkout <file>。 

版本回退

在 Git 中你可以使用 git reset commitID 把当前版本回退到之前提交的任意一个版本中。是不是觉得很熟悉!在上一节中使用过这样一个指令,git reset HEAD <file>,这其实是一个指令!在 Git 中,HEAD 表示最近一次提交,而最近一次提交的上一次提交可以用HEAD^,那上上一次呢?HEAD^^,上上上一一次?HEAD^^^,那……你懂得。还记得 git reset HEAD <file> 的作用吗?用最近一次提交中的文件替代暂存区中的文件。仔细想一想,其实版本回退就把所有文件都替换掉就好了!在 git reset 指令中,在不加 <file> 这个参数后,会把整个暂存区用对应提交中的文件替换掉。

特别注意一下,git reset commitID 只是回退了暂存区中的文件,工作区中的文件是不会改变的。举个栗子。目前我们的 activity_main.xml 如下:

我们回退到上一个版本,在上一个版本中我们的 activity_main.xml 中还没有添加最后一行。

执行后,查看 activity_main.xml,发现并没有改变!因为 git reset commitID 回退的是暂存区的内容,工作区的内容时不变的。如果你不信暂存区回退到上一个版本的话,可以用 git status 查看一下仓库状态,里面应该会有一条Changes not staged for commit,里面的内容是 modified: activity_main.xml。如果想把工作区也回退到上一个版本中的样子,可以在reset之后,执行 git checkout -- .将当前目录用暂存区的内容替代。或者可以直接使用 git reset --hard commitID,其中的--hard参数会使工作区和暂存区都被恢复成上一次提交时的样子。

要回退的版本可以直接用提交的 SHA1 值指定。提交的 SHA1 值可以用 git log 中看到。

用 SHA1值来回退到上一个版本就像这样。

git reset 命令可以将当前版本设置为任意一个提交,只要知道那个提交的 SHA1 值,就能用git reset 命令将它设置为当前版本。现在我们要把当前版本跳转回去,回到那个添加了 modifyTest 的版本去,我们用 git log 命令来查看这个版本的 SHA1 值,发现……并没有!

git log 只会显示当前版本之前的提交历史。不过还是有办法的,我们用 git reflog 指令,他记录了 HEAD 这个头指针变动的历史。

用查找到的版本号进行 git reset 操作就可以回去了。

Android Studio 中的相应操作 

在 Android Studio 中进行版本地方法如图所示,在 Version Control 的 Log 下,选中要跳转的版本,右键右键在弹出的菜单中,选择 Reset Current Branch to Here 即可。

.gitignore文件的使用

一般在使用 Git 时,会使用 git add -A 将工作区里的所有文件都更新到暂存区,但是总有些文件是我们不想添加进版本控制系统的(通常是一些自动生成的文件,想编译后产生的文件),这时要么一个一个添加文件,要么先全部添加,再把不要的删掉,很不方便。而且在每次用 git status 总会有大量的红字,提示我们有文件没添加进版本管理。使用 .gitignore 文件可以告诉 Git 哪些文件是不想纳入版本管理的,让 Git 把这些文件忽略掉。

在Android Studio 中,有两个 .gitignore 文件,一个是 Project 根目录下的,一个是 module 下的。对于 Android 项目,根目录下的 .gitignore 文件可以如下配置。

module 下的 .gitignore 文件可以如下配置:

如果还有什么需要忽略的文件,可以自行添加,添加的语法如上,其中#开头的是注释,*表所有,像 *.iml 表示所有后缀为 .iml 的文件。

配置前后用 git status 查看文件状态,可以发现我们指定的忽略文件已经被忽略了。

如果一个文件已经被检入到了暂存区里面,那么即使在 .gitignore 文件里添加这个文件名,Git 也不会忽略他。所以最好在一开始的时候就把 .gitignore 给配置好。如果很不幸地出现了这种情况,用下面的指令把相应的文件从暂存区里面删除即可。

既然已经把不需要的文件都忽略了,以后添加改动和提交只需要把他们全加上了!执行以下指令。

现在再用 git status 查看仓库状态,显示当前没有任何改动,工作树(工作区)是干净的。其实早就想这么干的,红字看的真心难受。。。

帮助: GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,参考地址为:

https://github.com/github/gitignore

备份代码到远程仓库

由于电脑可能会中途报废,我们可能需要个像云盘一样的东西用来备份。又或者在好多个地方有好多台电脑,今天在那里工作明天在这里工作,我们就需要一个地方来中转代码。又或者需要进行协同开发……

这里我们使用 Github 来创建远程仓库,当然也可以采用别的Git仓库托管服务,像码云, Bitbucket 等,当然自己搭也是可以的,在 Git 官网上有详细的教程。Github 账号是必须的,请自行注册。既然要在网络中传输数据,那必然要涉及到协议。目前 Git 传输数据最常用的两种协议是 SSH 和 HTTPS。

  • 使用SSH协议的方式

  • 配置SSH Key

在命令行中执行以下命令,生成 SSH Key。

$ ssh-keygen -t rsa -C "youremail@example.com"   // 把邮箱替换成自己的

输入后,他会让我们输入 Key 存放的位置,如果直接回车,那么默认就是冒号前面那段路径了,之后要根据这个路径找到 Key。

之后他还会叫你两次输入密码,如果没什么重要的东西,直接回车就好了。成功后应该是下面这个样子的。

然后来到生成 Key 的目录下面,有下图所示的两个文件,打开后缀为 .pub 的文件(这个是公钥,另一个是私钥),过会儿我们会要把它放到 github 的账户里。

按下图的步骤把SSH添加到账户里,按下Add SSH Key,就完成了SSH Key的配置。

  • 创建远程仓库

按下图进入创建远程仓库页面。

按下图创建一个远程仓库。Github 上的私人仓库是要钱的,7美元一个月哈。虽然是仓库公开的,但是因为有 ssh key,别人是不能直接修改你的代码的,不过他们可以看到你的代码。

点击创建后,就拥有自己的远程仓库啦!

  • 在本地添加远程仓库

现在我们已经创建好远程仓库了,我们在本地仓库把它添加上去,就可以把代码备份到远程库了。添加远程库的命令如下。

git remote add <shortname> <url>

其中 shortname 相当于是 url 的简称,以后用 shortname 就可以代表 url。url 是远程仓库的地址,可以在如下页面中得到。

一般用 origin 表示远程库。在我们的仓库里,执行以下命令。

$ git remote add origin git@github.com:WoHohohoho/MyApplication.git

可以用 git remote 来查看现有的远程库,上一个命令成功后再执行可以看到多了一个 origin 。

  • 把本地仓库的内容push到远程仓库

在添加完远程库后,可以用 git push [remote-name] [branch-name] 命令来将本地仓库中的内容推送到远程仓库上。其中 remote-name 是远程仓库名,就是上一步中我们设置的 shortname,branch-name 是分支名,分支的具体内容下面再介绍。git push 可以把本地的提交推送到远程仓库中,在执行时,本地仓库与远成仓库会比较提交历史,把远程仓库没有的提交挑选出来,然后发上去,完成更新。

与 git push 对应的还有 git pull [remote-name] [branch-name],push 是推,而 pull 是拉,当我们在另一台电脑上完成工作并推送提交到远程仓库后,为了在原来的电脑上继续工作,我们需要把远程仓库中的更新拉下来,更新本地仓库。

注意: 在使用 git pull 时,要保证本地仓库是最新的,即远程仓库中所有的提交本地都需要有,不然 Git 会提示 pull 操作失败。在一个人开发时,因为自己知道自己的代码是否是最新的,所以简单地使用 push 和 pull 就可以了。在多人开发中,由于别人也会向远程仓库提交代码,在每次 push 前需要先试探性的获取远程的更新,没有的话就直接 push,有的话需要把更新合并到本地的代码中,由于这涉及到分支和合并,之后再详细讲。

仓库初始化时,会默认创建一个 master 分支,我们的版本现在都在这个分支上,现在我们把这个分支推送上去就好了。

在我们的仓库里输入下列指令。

git push origin master

执行完成后,远程仓库里就存在了一份一模一样的工程。

以后每有更新,用 git push 将改动更新到远程仓库即可。

  • 使用 HTTPS 协议的方式

使用 HTTPS 协议操作起来比较简单。只要从使用 SSH 协议的第三步开始,将远程仓库的 url 换成 https 形式即可。

之后操作和 SSH 方式相同,不过在 push 和之后会提到的 fetch(拉取)时,会要求验证账号和密码,不过可以通过设置,来保存账户名和密码,而且一些客户端可以帮助存取账户名和密码,十分方便。HTTPS 虽然使用起来很方便,但服务器搭建时配置 HTTPS 比配置 SSH 麻烦许多。

Android Studio 中的相应操作 

可以直接在 Android Studio 连接 Github,建立远程仓库,完成推送。首先需要在 Android Studio 中设置对应 Github 的账号和密码。操作路径为 File->Settings->Version Control->Github。

其中 Clone git repositories using ssh 这个选项勾选了,就会使用 ssh 协议,不勾选就会使用 https 协议。用 Test 可以测试是否能够连接上 Github。使用 ssh 协议的话,在创建之前需要配置 SSH Key,方式和前面相同。

点击之后,可能会要求你输入密码等,最后会弹出一个如下对话框,填写信息,按下 Share 按钮,就完成了创建远程仓库,在本地添加远程仓库,推送代码到远程仓库的一系列操作,十分方便。

Android Studio 中的 push 操作和 pull 操作分别是 VCS->Git->Push和VCS->Git->Pull。

克隆

上一小节我们讲了怎么创建一个远程仓库并把本地仓库同步到上面去,这节会讲如何将远程仓库拷贝到本地来。以后,只要有一台能联网的电脑,我们就能继续我们的工作。

在 Git 中,可以用 git clone <remote-url> <local-directory> 来克隆远程仓库到本地。接下来,我们试着把上一节中创建的远程仓库 clone 到本地来。

我们执行以下命令,其中 remote-url 就是我们在创建远程仓库时得到的远程仓库的地址, local-directory 指明了我们要把仓库放在这个目录(文件夹)里,如果这个目录不存在,Git 会自动帮我们新建。

git clone git@github.com:WoHohohoho/MyApplication.git ~/Desktop/MyApplicationCloneVersio

执行完成后,打开对应目录,会发现东西都已经拷下来了,比 U盘什么的方便多了。

Android Studio中的相应操作 

Android Studio 中的 Clone 操作沿着 VCS->Git->Clone 路径可以找到。

之后填写相关参数即可,点击 Clone 即可。

由于篇幅限制,Git中的分支 这一章节省略,有兴趣的同学可以通过原文链接,去学习相关的内容。

用 Git 进行协同开发

在协同开发中,为了项目管理的方便,会采用各种各样的工作流,有关工作流方面的内容,可以到开头提供的第三个网址里学习。这里只简单介绍两个实用的技巧。

一个干净的push!

在 Git 中,我们很少会改变中央仓库的已有的提交历史。因为那样会使所有的开发者的本地仓库和中央仓库处在不一致的状态,所有开发者都需要因为这个改动调整自己的本地仓库来与中央仓库保持一致。如果改动很大,调整将会很复杂。只要不是及其严重的事情,我们都不会去调整中央仓库的提交历史。所以,推送上去是什么样的,以后就会是什么样的,对于中央仓库来说,第一印象会伴随一生。

所以,就像女生出门前要化妆一样,在推送本地分支到中央仓库前,要把本地分支整理干净。一般,我们会给每个功能新建一个分支,在功能开发完成后,可以用git rebase -i命令删去那些无关紧要的提交,并将提交历史书写成我们逻辑中的样子。

比如我们接到了生产车门的任务,现在我们把它完成了,开发历史如下。

在我们把它推送到中央仓库前,我们用 git rebase -i <commitID> 整理一下它的提交历史,commitID 参数用来指定我们要从哪个提交开始修改。由于我们是从 BetterWheelCompleted 这个提交开始开发车门的,所以 commitID 参数应该是这个提交的版本号,为 99c7ed1578c0a16a0f1de58548883a8d6e8eeb8a。执行以下指令。

git rebase -i 99c7ed1578c0a16a0f1de58548883a8d6e8eeb8a

之后,在命令行中会显示vi文本编辑窗口。

在最前面的是各个提交,每个提交的前面是要对该提交执行的命令,默认是pick采用提交,我们主要会用到 squash 命令,squash 命令可以让我们把对应提交合并到上一次提交中,举个栗子,给 69218a4 提交加上 squash 命令就可以把它合并到 f7a6770 提交上。我们开发车门主要有三个阶段,设计车架,设计车窗,加入手势开门功能,所以我们要分别合并第二、三、四次提交。我们把它编辑如下,然后保存并退出编辑窗口。

之后在合并第二、三、四次提交时,Git 又会弹出一个文本编辑窗口,让我们合并三次提交的提交信息。

因为这一次合并提交的信息应该为“设计了车窗”,刚好是第二个提交的提交信息,所以我们在不要的信息前加#把他们忽略即可。合并完成后,我们的提交历史就变成了如下模样。

然后就可以把他们推送到远端,由其他人检查代码,然后合并或者变基到主分支上了。如果在开发完后就已经决定要这条分支变基到主分支上,那也可以直接用 git rebase -i <branch_name> 来修改提交历史并变基。

很多时候,我们会把一个功能的实现分为好几个功能点,然后给功能点新建一条分支,然后在这个功能点开发完后把修改整合回功能分支。这样做的好处是可以保持功能分支的整洁,不会在功能分支上生成很多备份代码的提交,但是如果用普通的 merge 操作的话,合并生成的提交除了指向主功能分支外,也会指向功能点分支,那样还是会把功能点分支上的提交历史混合进来。

这时我们可以使用 git merge --squash <branch_name>,在 merge 指令中加入 --squash 后会把 branch_name 分支上的所有提交压缩成一个加入到当前分支上来,并且这个提交不会指向被合并的分支。举个栗子,在上次我们把车门的分支推送上去给老大检查后,老大说要再加一个手势关门的功能!然后我们为了主分支的整洁,给这个小功能新建了一个分支进行开发。接着,经过了不懈努力,我们终于开发完了,现在提交历史如下。

我们用以下指令把 feature-CloaseDoorwithGesture 分支的上的提交压缩成一个一条放到 produceDoor 分支上。

执行完成后我们的提交历史就变成了下图所示模样。

可以看到新建的提交并没有指向 feature-CloaseDoorwithGesture 分支。在合并完后,我们可以删除 feature-CloaseDoorwithGesture 分支。

$ git branch -D feature-CloseDoorwithGesture

OK。老大说干的不错,让我们把分支合并到主分支上,然后推送到中央仓库来结束这个功能的开发。

执行完成后,提交历史如下。

Android Studio 中的相应操作 

用 VCS->Git->Merge Changes 下的合并操作,并选中 squash commit 选项,即可完成 git  merge --squash <branch_name> 操作。

git rebase -i <commitID> 可以用 VCS->Git->Rebase 完成。点击后会弹出如下对话框,选中 Interactive 选项,在 Branch 选项中选中要变基的分支,在 Onto 选项中,填写新基点(会从这个提交开始修改历史)。

点击 Rebase 之后,会弹出如下对话框, 在这里你可以选择要对每个提交执行的命令。选完命令之后,按下 Start Rebasing 就会开始变基。

push失败?

我们把前面开发车门那个同学叫做小明,在小明开发车门,引擎和轮子的同时,还有一个叫小刚的同学在开发制动系统。小刚现在刚把制动系统开发完毕,他现在的提交历史如下。

现在他要把 master 分支推送到中央仓库上。小刚运行了如下指令。

git push origin master

但是 Git 告诉他,push 被拒绝了,因为中央仓库的 master 分支里有本地还没有的改动,并让我们把改动集成到本地仓库中再进行 push。

所以在每次 push 前,应该先抓取中央仓库上的更新,然后集成到本地,再提交。抓取更新的指令是 git fetch <remote_name> <branch_name>。现在小明用以下指令拉取了中央仓库上的更新。

git fetch origin master

拉取后,本地的提交历史变成了这样。其中,origin/master 表示的就是远程仓库上的 master 分支,远程分支是只读的,不能修改。

现在小明要把远程仓库的 master 分支上的改动集成到本地的 master 上。根据之前学的知识,有两种方法,rebase 和 merge。

如果使用 merge,把本地 origin/master 分支的内容合并到 master 上,合并后提交历史如下。很乱,而且因为合并而新生成了一个节点。

如果用 rebase,把本地 master 分支的内容变基到 origin/master 上,合并后提交历史如下。清楚了很多,而且看起来像是串行开发的一样。一般把远端更新整合到本地会用rebase 指令。

注意: rebase 操作会把可以快进的合并记录删掉,最后 rebase 结果就像是合并时使用了快进一样。如果要保留合并记录,可以加入 --preserve-merges 参数。

上面提到过 git pull <remote_name> <branch_name> 操作,它其实是 git fetch <remote_name> <branch_name>和 git merge 的结合。当然也可以转化为 rebase 版本,在中间加个参数,git pull --rebase <remote_name> <branch_name>。

其实上面的操作有更好的处理方法。在功能开发完成后,可以先把远端的更新用 git pull --rebase 拉取下来,并把本地分支的更新变基到上面去。之后,把功能分支 rebase 到主分支上,这个时候远端的更新就全部整合进功能分支了,这个时候我们可以测试一下合并之后代码还正不正确。最后再把功能分支合并到主分支并推送上去。

Android Studio 中的相应操作 

在 Android Studio 中,可以选择用 merge 版本还是rebase版本的 pull 操作。按下下图中的按钮。

在弹出的对话框中,选择拉取方式。右边的选项是存储当前工作区修改的方式。选择完成后,点击 ok 即可开始拉取。

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。

如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值