源码管理工具之git的使用

一、git简介

git是目前世界上被最广泛使用的现代软件版本管理系统。git本身亦是一个成熟并处于活跃开发状态的开源项目,它最初是由Linux操作系统内核的创造者Linus Torvalds在2005年创造。

二、在Mac OS X上安装git

如果你正在使用Mac做开发,有两种安装git的方法。

  • 安装homebrew,然后通过homebrew安装git,具体方法请参考homebrew的文档:http://brew.sh/
  • 直接从AppStore安装XcodeXcode集成了git。不过默认没有安装,你需要运行Xcode,选择菜单“Xcode”->“Preferences”,在弹出窗口中找到“Downloads”,选择“Command Line Tools”,点“Install”就可以完成安装了。

三、创建本地仓库

仓库:英文名repository,可以简单理解成一个目录,这个目录里面的所有文件都可以被git管理起来,每个文件的修改、删除,git都能记录,以便任何时刻都可以查找历史记录,或者在回滚到以前修改的状态。

1、首先,选择一个合适的地方,创建一个空目录,执行:

git init

创建新的git仓库,会发下在当前的创建的目录下面多了一个.git的目录,这个目录是git来管理仓库的。 注意: 没事千万不要手动修改这个目录里面的文件,不然就把会git仓库给破坏了。

2、添加文件到git仓库

把文件添加到仓库:

git add <filename>
git add .

注意: git add <filename>是把某一个文件添加到git的缓存区里面。 git add .是把所有的文件添加到git的缓存区里面。

3、把文件提交到本地仓库

git commit -m "代码提交信息"

注意:

  • git commit命令,一般会在后面加上-m表示本次提交到本地仓库的记录。
  • commit message言简意赅,不要写无用信息,这样让别人不能看懂这次提交的意义。
  • 在开发时,良好的习惯是根据工作进度及时commit,并务必注意附上有意义的commit message。创建完项目目录后,第一次提交的commit message一般为Initial commit.
  • 添加一个新的Pod库或pod update后,要单独提交一个commit,统一commit messagepod add xxxpod update xxx

四、远程仓库

一般使用git的公司都会有自己的git服务器或者使用第三方git服务器,比如coding.net、码云等。 由于你的本地git仓库和git服务器仓库之间的传输是通过SSH加密的,需要设置:

  • 创建SSH Key。在用户主目录下,看看有没有.ssh目录。如果有,再看看这个目录下有没有id_rsaid_rsa.pub这两个文件,如果已经有,可直接跳到下一步。如果没有,打开Shell,创建SSH Key
ssh-keygen -t rsa -C "your.email@example.com" -b 4096
  • 将公共SSH密钥复制到剪贴板:
pbcopy < ~/.ssh/id_rsa.pub
  • 登陆git服务器,打开“Account settings”“SSH Keys”页面:
  • “Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:

image.png

注意: 为什么git服务器需要SSH Key呢?因为git服务器需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而git支持SSH协议,所以,git服务器只要知道了你的公钥,就可以确认只有你自己才能推送。

当然,git服务器允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到git服务器,就可以在每台电脑上往git服务器推送了。

五、添加远程仓库

  • 登陆git服务器,然后,找到“Create a new repo”按钮,创建一个新的仓库:
  • Repository name填入learngit,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的git仓库。 注意: 目前,在git服务器上的这个learngit仓库还是空的,git服务器告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到git服务器仓库。

image.png

通过上图可以看出: 1、如果在本地没有创建仓库,可以通过下面命令从git服务器clone出一个新的仓库:

git clone http://michael@git.51fanxing.com:88/fxbest/ios/learngit.git
cd learngit
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master

2、如果本地已经创建了,可以通过下面命令把本地仓库与git服务器仓库进行关联:

cd existing_folder
git init
git remote add origin http://michael@git.51fanxing.com:88/fxbest/ios/learngit.git
git add .
git commit
git push -u origin master

注意: 1、git remote add origin表示将本地服务器与git服务器进行关联。 2、origingit服务器的别名,取什么名字都可以,你也可以在push时将git服务器替换为 origin。但为了以后push方便,我们第一次一般都会先remote add。 3、git push -u origin master将你修改或者添加的文件提交到git服务器。

3、git remote git remote命令允许你创建、查看和删除和其它仓库之间的远程连接。

git remote

列出和其他仓库之间的远程连接。

git remote -v

列出和其他仓库之间的远程连接,但同时显示每个连接的URL

git remote add <name> <url>

创建一个新的远程仓库连接。在添加之后,可以将<name>作为<url>便捷的别名在其他git命令中使用。

git remote rm <name>

移除名为的远程仓库的连接。

git remote rename <old-name> <new-name>

将远程连接从<old-name>重命名为<new-name>

六、检查仓库状态

1、git status git status命令显示工作目录和缓存区的状态。你可以看到哪些更改被缓存了,哪些还没有,以及哪些还未被git记录。

2、git log git log命令查看每次commit的历史记录。

git log

使用默认格式显示完整地commit记录,如果输出超过一屏,你可以用空格键来滚动,按q退出。

git log -n <limit>

用<limit>限制提交的数量,比如git log -n 3只会显示3个提交。

git log --oneline

将每个提交压缩到一行,当你需要查看项目历史的上层情况时这会很有用。

git log --stat

除了git log信息之外,包含哪些文件被更改了,以及每个文件相对的增删行数。

git log -p

显示代表每个提交的一堆信息,显示每个提交全部的差异(diff),这也是项目历史中最详细的视图。

git log --author="<pattern>"

搜索特定作者的提交。<pattern>可以是字符串或正则表达式。

git log --grep="<pattern>"

搜索提交信息匹配特定<pattern>的提交。<pattern>可以是字符串或正则表达式。

七、git reset、git checkout和git revert

git仓库有三个主要组成——工作目录,缓存区和提交历史。

image.png

git resetgit checkoutgit revert是你的git工具箱中最有用的一些命令。它们都用来撤销代码仓库中的某些更改,而前两个命令不仅可以作用于提交,还可以作用于特定文件。

因为它们非常相似,所以我们经常会搞混,不知道什么场景下该用哪个命令。

1、git reset

git reset操作会将当前分支的HEAD指向另外一个commit记录,这样可以在当前分支上移除部分commit记录。例如,在hotfix分支上回滚前两次的commit状态:

git reset HEAD~2

image.png

image.png

当执行git reset时,hotfix分支上最后两次提交的状态会变成空状态,等到git执行垃圾回收的时候,hotfix分支上最后两次提交的状态会被回收。

  • --soft – 缓存区和工作目录都不会被改变
  • --mixed – 默认选项。缓存区和你指定的提交同步,但工作目录不受影响
  • --hard – 缓存区和工作目录都同步到你指定的提交

git reset一般配合这些参数使用,git reset --mixed HEAD将你当前的改动从缓存区中移除,但是这些改动还留在工作目录中。如果你想完全舍弃你没有提交的改动,你可以使用git reset --hard HEAD,这是git reset最常用的两种用法。 注意: git reset是不可逆的,因为git reset操作会重写当前分支的历史,用来撤销缓存区和工作目录的修改。git reset只适用于本地修改,不能重设服务器上的commit记录。

2、git checkout

  • 切换分支:
git checkout hotfix

注意: 使用git checkout之前,要把工作区的内容提交到git服务器或者缓存区。git checkout是将HEAD指针从一个分支切换到另一个分支,然后更新工作目录。因为这可能会覆盖本地的修改,git会强制你提交或者缓存工作目录中的所有更改,不然在checkout的时候这些更改都会丢失。

image.png

image.png

  • 查看文件之前的版本

除了切换分支之外,git checkout还可以将HEAD指针移动到当前分支其他的commit记录。

git checkout HEAD~2

git checkout更改的是工作目录而不是缓存区

git checkout HEAD~2 xxx

如果你缓存并且提交了checkout的文件,它具备将某个文件回撤到之前版本的效果,注意它撤销了这个文件后面所有的更改。不影响你仓库的当前状态。你可以在新的快照中像其他文件一样重新提交旧版本。所以,在效果上,git checkout的这个用法可以用来将单个文件回滚到旧版本。

image.png

image.png

注意: git checkout是可逆的。

3、git revert

git revert撤销一个commit记录的同时会创建另一个新的commit记录,这是一个安全的方法,而不是从项目历史中移除这个提交。这避免了git丢失项目历史记录,这一点对于你的版本历史和协作的可靠性来说是很重要的。

比如,下面的命令会找出倒数第二个提交,然后创建一个新的提交来撤销这些更改,然后把这个提交加入项目中。

git revert HEAD~2

image.png

image.png

git revert应该用在你想要在项目历史中移除一整个提交的时候。比如说,你在追踪一个 bug,然后你发现它是由一个提交造成的,这时候撤销就很有用。与其说自己去修复它,然后提交一个新的快照,不如用git revert,它帮你做了所有的事情。

git revert回滚了单独一个提交,它没有移除后面的提交记录,同时会创建另一个新的commit记录。

image.png

git reset回滚了单独一个提交,并且移除后面的提交记录,是不可逆的

image.png

git revert可以针对历史记录中任何一个提交,而git reset只能从当前提交向前回滚。比如,你想用git reset重设一个旧的提交,你不得不移除那个提交后的所有提交,再移除那个提交,然后重新提交后面的所有提交。一般公司不提倡这么做。因此,git revert可以用在公共分支上,git reset应该用在私有分支上。

4、git reset用慎用 当有commit之后的提交被推送到公共分支上,你绝不应该使用git reset。使用git reset回滚了单独一个提交,并且移除后面的提交记录。当团队成员在上面继续开发的提交在协作时会引发严重的问题。当他们试着和你的仓库同步时,他们会发现项目历史的一部分突然消失了。 下面的序列展示了如果你尝试重设公共提交时会发生什么。origin/master是你本地master分支对应的中央仓库中的分支。

image.png

image.png

image.png

一旦你在重设之后又增加了新的提交,git会认为你的本地历史已经和 origin/master分叉了,同步你的仓库时的合并提交(merge commit)会使你的同事困惑。

5、git clean

git clean命令将未记录的文件从你的工作目录中移除。它只是提供了一条捷径,因为用git status查看未记录的文件,然后手动移除它们也很方便。和一般的rm命令一样,git clean是无法撤消的,所以在删除未记录的文件之前想清楚,你是否真的要这么做。

git clean命令经常和git reset --hard一起使用。记住,git reset只影响被记录的文件,所以还需要一个单独的命令来清理未被记录的文件。这个两个命令相结合,你就可以将工作目录回到之前特定提交时的状态。

注意: git clean也是不可逆的。

八、分支

1、git branch 分支代表了一条独立的开发流水线,git branch命令允许你创建、列出、重命名和删除分支。一般git branchgit checkoutgit merge这两个命令通常紧密地结合在一起使用。一般使用过git的同学都知道:

  • master是长期分支,一般用于管理对外发布版本,每个commit对一个tag,也就是一个发布版本。
  • develop是长期分支,一般用于作为日常开发汇总,即开发版的代码
  • feature是短期分支,一般用于一个新功能的开发。
  • hotfix是短期分支 ,一般用于正式发布以后,出现bug,需要创建一个分支,进行bug修补。
  • release是短期分支,一般用于发布正式版本之前(即合并到master分支之前),需要有的预发布的版本进行测试。release分支在经历测试之后,测试确认验收,将会被合并的developmaster
git branch

列出仓库中所有分支。

git branch <branch>

创建一个名为 <branch> 的分支。不会自动切换到那个分支去。

git branch -d <branch>

删除指定分支。这是一个安全的操作,git会阻止你删除包含未合并更改的分支。

git branch -D <branch>

强制删除指定分支,即使包含未合并更改。如果你希望永远删除某条开发线的所有提交,你应该用这个命令。

git branch -m <branch>

将当前分支命名为<branch>。

2、git merge 用于合并指定分支到当前分支,git merge命令允许你将git branch创建的多条分支合并成一个。

注意: 合并指定分支到当前分支,当前分支会被更新,以响应合并操作,但目标分支完全不受影响。也就是说git merge经常和git checkout一起使用,选择当前分支,然后用git branch -d删除废弃的目标分支。

git merge <branch>

将指定分支并入当前分支。

git merge --no-ff <branch>

将指定分支并入当前分支,但 总是 生成一个合并提交(即使是快速向前合并)。这可以用来记录仓库中发生的所有合并。

3、git merge几种方法

  • 快速向前合并 当当前分支顶端到目标分支路径是线性之时,我们可以采取快速向前合并。git只需要将当前分支顶端(快速向前地)移动到目标分支顶端,即可整合两个分支的历史,而不需要“真正”合并分支。它在效果上合并了历史,因为目标分支上的提交现在在当前分支可以访问到。比如,some-featuremaster分支的快速向前合并会是这样的:

image.png

image.png

  • 三路合并 如果分支已经分叉了,那么就无法进行快速向前合并。当和目标分支之间的路径不是线性之时,git只能执行三路合并。三路合并使用一个专门的提交来合并两个分支的历史。这个术语取自这样一个事实,git使用三个提交来生成合并提交:两个分支顶端和它们共同的祖先。

image.png

image.png

很多开发者喜欢使用git rebase快速向前合并,来合并微小的功能或者修复bug,使用三路合并来整合长期运行的功能。后者导致的合并提交作为两个分支的连接标志。

4、解决冲突

如果你尝试合并的两个分支同一个文件的同一个部分,git将无法决定使用哪个版本。当这种情况发生时,它会停在合并提交,让你手动解决这些冲突。

当你遇到合并冲突时,运行git status命令来查看哪些文件存在需要解决的冲突。

当你手动修复完冲突之后,只需对冲突的文件运行git add告诉git冲突已解决。然后,运行git commit生成一个合并提交。

使用git log --graph命令可以看到分支合并图。

团队合作的分支看起来就像这样:

image.png

注意: 提交冲突只会出现在三路合并中。在快速向前合并中,我们不可能出现冲突的更改。

九、创建标签

一般在公司每一个上线版本都会打一个标签,为了记录和维护,当线上版本出现紧急bug,我们就可以通过git checkout检出项目,然后创建hotfix分支进行bug的修复。

git tag

查看所有标签

git tag <name>
git tag <name> commit id

用于新建一个标签,默认为HEAD,也可以指定一个commit id

git show <tagname>

查看标签信息

git push origin <tagname>

可以推送一个本地标签

git push origin --tags

可以推送全部未推送过的本地标签

git tag -d <tagname>

可以删除一个本地标签

git push origin :refs/tags/<tagname>

可以删除一个远程标签

Reference: https://www.atlassian.com/git/tutorials/merging-vs-rebasing https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

Linux 下各文件夹的结构说明及用途介绍

/home:用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示。

1360
来自专栏『不羁阁』行走的少年专栏

Hexo 博客部署到腾讯云教程

5415
来自专栏北京马哥教育

Linux运维常见故障排查和处理的33个技巧汇总

作为linux运维,多多少少会碰见这样那样的问题或故障,从中总结经验,查找问题,汇总并分析故障的原因,这是一个Linux运维工程师良好的习惯。每一次技术的突破,...

4366
来自专栏Rovo89

安装SSserver和配置(二)

1.5K3
来自专栏owent

基于Chrome插件的开发工具链

在项目开发过程中,时不时会碰上需要使用一些工具来做一些自动操作或者附加功能。特别是有一些外部组件只会提供Web工具,或者如果产品会发布在Web上的时候,在线上的...

1252
来自专栏农夫安全

常见Web源码泄露总结

? .hg源码泄漏 漏洞成因: hg init的时候会生成.hg e.g.http://www.example.com/.hg/ 漏洞利用: 工具:dvc...

4486
来自专栏程序员宝库

Linux 下各文件夹的结构说明及用途介绍

linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令。 /dev:设备特殊文件。 /etc:系统管理和配置文件。 /etc/rc.d:启动的配...

44912
来自专栏difcareer的技术笔记

Android boot.img的解包/修改/重打包

最近研究对了Android的boot.img的操作,将一些繁琐的东西整理了一下,发到了github:https://github.com/difcareer/B...

3425
来自专栏owent

Gitlab环境搭建小计

Gitlab 开源仓库软件包官方地址: https://about.gitlab.com/

1091
来自专栏林德熙的博客

Roslyn 通过 nuget 统一管理信息

在日常的开发中,如果需要发布多个库,多个库之间的版权和作者等信息都是相同的。如果需要每次更改信息都打开项目进行编辑,这个效率是很低的。本文提供一个方式,通过安装...

962

扫码关注云+社区

领取腾讯云代金券