git实战指南
August 1, 2017
今天在往公司的gitlab上push项目的时候死活无法push上去,总是显示没有权限。报错信息上显示sshkey
的问题,但是我在github上面都是好好的,搞了半天,我都翻出里git的配置文件改了好几遍都没有用,总之就是个垃圾。。。,后来我放弃了git协议,使用http协议手动认证身份就可以了。傻逼的错误信息如下:
sign_and_send_pubkey: signing failed: agent refused operation
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
虽然体验不是很好但是用到了很多以前没有机会用的命令,实践出真知,今天就来总结一下实战中的git是怎么玩的。
安装 #
$ sudo apt install git
配置config #
在终端直接输入以下命令:
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
这个一般我们安装好就会配置一下,这个是全局的配置,如果你的项目中没有自己的配置就会使用这个配置。关于git的配置,你可以用如下的命令查看都有那些信息:
$ git config -l
这会列出全局+当前目录下的git仓库的信息。如果你所在的目录不是个git仓库就只列出全局的配置信息。
当你不加-l
的选项的时候,就会列出config常用的选项,其中有一些选项可以用来修改配置信息。这个当你需要用的时候自己在终端看一下就可以了。
其中也告诉我们,git的配置可以每个项目都有一个配置,这个配置就在你的仓库.git/
文件夹下的config
文件中。全局的配置在~/.gitconfig
文件中。
ssh key #
在终端生成一个ssh key
的命令如下:
$ ssh-keygen -t rsa -C "e-mail@xxx.com"
生成的密钥和公钥在~/.ssh/
文件夹下,你需要将你的后缀.pub
的那个文件的内容复制出来,放到你的github或是公司的gitlab上。当然了,gitlab就算了吧,因为貌似不会起作用。
工作区 & 本地仓库 & 远程仓库 #
初学git的人往往分布清楚这几个的概念。那就画个图来说明一下简单直观。 (此处有图)
工作区 #
首先你要知道的是你写的文件,并不在git的概念中。啥意思呢,就是你写的文件就是你写的文件,git又不管你在这个文件夹下面写了什么东西,git的第一个空间是:工作区。当你将你的修改或是新写的文件通过git add
的命令提交的时候这写文件才会被git记录下来,这时候是放到了工作区了。
既然是工作区,相对的自由度就大一些,你可以添加进去,然后当你要提交的时候觉得这个东西写的还不是很好,你想再继续开发一段时间再发布出去,这个时候你就可以使用 git checkout <文件>...
来丢弃工作区的改动。
相当于工作区放的都是你完成的产品,即将被发布。
本地仓库 #
当你觉得这次开发完成了,所有完成的作品也都放到工作区了。你就可以将整个工作区整体提交给本地仓库,使用如下命令:git commit -m 'say something'
。 say something
就是你在提交的时候简单的说一下这次你做了哪些东西。
仓库才是真正的git的领域,也是git的精髓所在,版本控制的集大成者。
一个仓库可以有很多个分支。这个分支是我们经常用到的,想比较而言,版本回退我们倒不是经常用到。什么时候会用版本回退呢?就是在我们发布的版本出现一些问题的时候,这个时候不能让一个有问题的东西给人用啊,所以就只好暂时版本回退到一个稳定版本,新功能暂时没有,不就没有问题了嘛!没错,程序员就是这样的逻辑,把报错信息删掉不就没有错误了嘛! 那么什么时候用分支呢?就是在开发的过程中嘛。多人协作,大家做的东西可能是不同的模块的,有的人做的模块可能要在未来的很多版本以后才能上线,这个时候总不能把自己的半成品也放到项目里发出去吧,所以干脆,你拉一个分支出去,等你开发结束了,再把这个分支合进主分支里好了。还有一些是什么情况呢?比如你开发到一定程度,接下来有两个方案,你不确定要做哪个,你可以都开发看看嘛,一般就是两波人。怎么办呢,两波人各拉一个分支出去,各自开发测试,等到开发完了,比较一下用哪个好,再合进主分支里发布。
关于git开发流的使用,有那么几个主流的使用方式,这个下次再补充进来。
本地仓库有很多分支喽,那么我这次提交要提交到哪个分支呢?
你当然要看一下当前有哪些分支喽:
$ git branch
# 结果如下:
* master
带*
号的分支就是你当前的默认分支,如果你不指明提交到哪个分支就是这个分支了。
master
就是你建仓库时的主分支了。
你现在只有一个分支,突然这一刻你林纳斯灵魂附体,你有个绝佳的想法,于是你新建了一个分支要开发一个新的小功能,于是你就建了一个分支, 并把当前的默认分支改成了你的新分支,因为你觉得这个想法太棒了,你留着之前的那段代码只是为了纪念自己曾经傻逼过:
$ git branch Linux
$ git checkout Linux
一切行云流水的结束了,因为只是简单的两个命令而已。同时结束的当然还有林纳斯投错胎的灵魂附体,于是你看着这个新的分支陷入了沉思,不过并没有关系,这个伟大的名字并不能改变你的命运,毕竟你曾经傻逼过嘛,都是可以原谅的,于是你删掉了这个分支,继续傻逼下去:
$ git branch -D Linux
远程仓库 #
你可以看到有哪些远程仓库:
$ git remote
或是更详细看看,你从哪些仓库同步代码和向那些仓库推送变更:
$ git remote -v
你也可以看看有哪些远程分支:
$ git branch -a
# 结果如下:
* master
remotes/origin/HEAD -> origin/master
remotes/origin/developing
remotes/origin/master
remotes
就是远程分支, HEAD
指明了这个远程仓库的当前分支是哪一个。
在下面有这个远程仓库的分支描述:remotes/仓库名/分支名
当然这个命令不报错是在你有远程仓库的前提下,如何建立远程仓库呢?别天真了,我怎么会告诉你呢?我也不会在本地建出来远程仓库,不过我会在远程建好了再建立连接。
先去github上建一个,反正没有钱搞gitlab
这个垃圾。在建完仓库的页面中有一些提示的,其中有个这样的命令
$ git remote add origin git@git...
你可以用这个命令将本地仓库与这个远程仓库建立连接,其中origin
是你给这个仓库起的名字,一般我们都是这个名字,毫无新意但是管用。
当然你也可以有多个远程仓库,就用上面这个命令就可以了,像个多面间谍一样向不同的仓库推送不同的代码。
注意啦! 怎么给不同的仓库推送不同的代码?如果你问了这个问题,说明你好像跟之前的我一样笨。 推送代码并不是仓库与仓库之间的行为,而是分支与分支的行为。
也就是说你可以推送本地的某个分支给远程的某个仓库的某个分支,用这个命令,很简单的:
$ git push -u origin master:developing
origin
就是你要推的远程仓库,master
是你本地的分支名,developing
是origin
仓库中的分支。如果不加冒号及后面的东西,就是推到目标远程仓库的默认当前分支。
这样这几个的关系应该就明白了。
本地如何优雅的使用git #
经常用下面这个命令
$ git status
这会列出当前这个文件夹下你有哪些修改过的文件还没有add
到工作区,有哪些文件是新的还没有add
到工作区。。。
貌似就是这样了吧,再优雅的姿势我就不太会了。
如何解决问题哒? #
将git
协议的连接转换成http
协议的连接并没有相应的命令可以使用,我是找到了仓库文件夹下的.git/config
文件,文件内容如下:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = http://gitlab.alibaba-inc.com/tair/xxxxxx.git
fetch = +refs/heads/*:refs/remotes/origin/*
[user]
email = bai@xxx.com
name = bai
将其中的url
从git
协议链接改成了http
协议的链接就可以了。
有冲突怎么办? #
业界潜规则嘛,早提交的早下班,晚提交的改冲突。
当push
的时候发现跟上面版本不一致了,落后于远程的仓库,就得先同步下来。
当我们pull下来的时候,发现跟本地的内容有冲突。这个时候就会在本地的文件中多出许多标记,标记如下:
<<<< head
// 这里是你本地的内容
========
// 这里是远程pull下来的内容
>>>> 02XSFDDFDFA123A
手动合并,然后再pull。
错误的git pull怎么办 #
在你同步远端的时候,发现远端与你的不同太多,你需要新拉一个分支,保留自己目前的分支的时候,你需要回退到之前的某个版本。一般就会退到pull之间的版本,所以下面的命令:
git reset --hard HEAD
回退两个commit:
git reset --hard HEAD^
查看历史的commit记录,选择退到某个版本:
git log
上面命令中的HEAD
可以换成任何一个历史commit的编号ID。like this : 40a85d646d6f6b05bac2bf5ce2b9a1f44ed74d4d