git使用说明
正确的版本控制系统的使用方法是: 一次提交只干一件事, 或者完成一个新的功能, 或者是修改了一个Bug
install and configure
install
- sudo apt-get install git-core
- sudo apt-get install openssh-server
- sudo apt-get install openssh-client
- sudo service ssh start
configure git user
- add git user
新加用户git,该用户将作为所有代码仓库和用户权限的管理者 sudo adduser git
2. 禁用shell登录
出于安全考虑,创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成. git:x:1001:1001:,,,:/home/git:/bin/bash 改为: git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
在这之后,通过执行su git 可能会报错:
git-shell报错
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
解决方法:将目录/usr/share/doc/git/contrib/git-shell-commands拷贝到git用户下/home/git/
修改所有者chown -R git.git git-shell-commands
如果该目录下的help和list没有执行权,那么再给它加执行权
chmod +x /home/git/git-shell-commands/help
chmod +x /home/git/git-shell-commands/list
init git repo
先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令: $ sudo git init --bare sample.git Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以 不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。 然后,把owner改为git: $ sudo chown -R git:git sample.git git裸仓库,就是指没有工作目录的仓库。简单点说,裸仓库就是工作目录下面的 .git 子目录里面的内容。远程仓库,一般不需要工作目录,所以通常都是裸仓库。
部署代码到服务器
如何将本地已有代码部署到服务器上,并且仅仅部署成一个裸仓库呢?
方式1
$ mkdir cdr $ cd cdr $ git init . $ git add ./ $ git commit -m "add uvc camera, and support change preview" $ git clone --bare cdr/ cdr.git 将生成的cdr.git拷贝到服务器 sudo scp -r cdr.git /Repo/ sudo chown -R git:git cdr.git 检出副本: git clone git@localhost:/Repo/cdr.git/
方式2
把本机的.git目录部署到服务器上,然后改成裸仓库 例如: scp -r .git git@server:/Repo/cdr.git
文件的几种状态
- unstaged - git仓库中没有此文件的相关记录
- modified - git仓库中有这个文件的记录,并且此文件当前有改动
- staged - 追加,删除或修改的文件被暂时保存,这些追加,删除和修改并没有提交到git仓库
- commited - 追加或修改的文件被提交到本地git仓库(git仓库中大部分都是这种文件,所以git status不显示这些文件)
常用命令
git config
git的三个配置文件分别是:
- 版本库级别的配置文件(.git/config) git config -e
- 全局配置文件(~/.gitconfig) git config -e –global
- 系统级配置文件(/etc目录下) git config -e –system
例:
git config --global user.name "caodan" git config --global user.email "caodan@linuxtoy.cn" git config --global color.ui true git config --global core.editor vim git config --global gui.encoding utf8
git add (提交到暂存区)
git add [path] 添加指定的文件到暂存区 git add -u [path] 将path中所有tracked文件中被修改过或者已删除文件的信息添加到暂存区, 但不会处理untracked的文件 git add -A [path] 把path中所有tracked文件中被修改过或已删除文件和所有untracted的文件 信息添加到暂存区
git commit(提交到本地仓库)
- 修改本次提交的commit
git commit –amend 修改之前的提交comment
git diff(差异比较)
- 工作空间与暂存区进行比较
git diff
修改后的文件通过git add命令提交到暂存区后,再执行git diff 命令后,将看不到该文件的差异 继续对该文件进行修改,再次执行git diff 命令,会看到新的修改显示在差异中,而看不到旧的修改
2. 工作空间与HEAD进行比较
git diff HEAD
HEAD是当前活跃分支的游标,可以认为HEAD(大写)是“current branch”(当下的分支) 使用git checkout切换分支的时候,HEAD 指向新的分支。有的时候HEAD会指向一个没有分支名字的修订版本,这种情况叫”detached HEAD“
3. 暂存区与HEAD进行比较
git diff --cached
- 比较两个版本的变化,只显示文件名
git diff --name-only [HEAD|--cached]
中括号中的参数同1、2、3点中所述 5. 文件不同版本间的比较
git diff <commit1> <commit2> -- <paths>
6. 比较一个文件在两个tag之间的不同
git diff tag1:file tag2:file
# 版本回退 git reset [--soft | --hard ] [<commit>] git reset –soft 回退到某个版本,不会恢复到index file一级。 git reset –hard 彻底恢复到某个版本,本地文件也会恢复到指定版本的内容。 HEAD 表示当前版本 HEAD^ 表示上一个版本 HEAD^^ 表示上上个版本 HEAD~100 表示上100个版本 例: 新建了一个版本库 test, 总共有3次提交$ git log commit 20c210c9949875df94172d3269433bcd6200d7c7 Author: xxx <xxx@xxx.cn> Date: Sun Dec 13 22:13:20 2015 +0800 free software commit 03f430b9474231fcb7fdb5527cec27f9146ab584 Author: xxx <xxx@xxx.cn> Date: Sun Dec 13 22:12:00 2015 +0800 add descriptions commit bfed7fb5d163c02ca66fac05d8f1b14961ba7f1a Author: xxx <xxx@linuxtoy.cn> Date: Sun Dec 13 22:11:15 2015 +0800 init test prj
回到到上一个版本:$ git reset --hard HEAD^ HEAD is now at 03f430b add descriptions $ git log commit 03f430b9474231fcb7fdb5527cec27f9146ab584 Author: xxx <xxx@linuxtoy.cn> Date: Sun Dec 13 22:12:00 2015 +0800 add descriptions commit bfed7fb5d163c02ca66fac05d8f1b14961ba7f1a Author: xxx <xxx@linuxtoy.cn> Date: Sun Dec 13 22:11:15 2015 +0800 init test prj
回退之后,log里面只能看到两次提交记录,如果要撤销回退,怎么才能回到刚才的版本? 如果还记得版本的commit id, 例如20c210c, 那么可以使用如下方式指定回退到未来的某个版本。 版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。$ git reset --hard 20c210c HEAD is now at 20c210c free software
如果不记得未来版本的commit id, 那怎么办? git 提供了一个命令 git reflog来记录你每次的操作, 可以查找到commit id$ git reflog 03f430b HEAD@{2}: reset: moving to HEAD^ 20c210c HEAD@{3}: commit: free software 03f430b HEAD@{4}: commit: add descriptions bfed7fb HEAD@{5}: commit (initial): init test prj
# 远程仓库与分支 ## 查看远程仓库信息
git remote 列出已经存在的远程仓库 git remote -v 列出远程仓库的详细信息,每个名字后面列出其远程url git remote show <remote-name> 查看单个远程仓库的信息
例如:$ git remote -v origin git@linuxtoy.cn:/data/repo/mywiki.git (fetch) origin git@linuxtoy.cn:/data/repo/mywiki.git (push)
$ git remote show vimrc * 远程 vimrc 获取地址:https://github.com/caodan4linux/vimrc 推送地址:https://github.com/caodan4linux/vimrc HEAD分支:master 远程分支: master 已跟踪 为 'git push' 配置的本地引用: master 推送至 master (最新)
## 添加或删除远程仓库 git remote add <name> <url> 添加一个位于url的命名为name的远程仓库 git remote remove <name> git remote rename <oldname> <newname>
例如:git remote add origin https://github.com/try-git/try_git.git
## 推送到远程仓库 git push [-u] <远程主机名> <本地分支名>:<远程分支名>
1. 如果省略远程分支名,则表示本地分支推送到已跟踪的远程分支(通常两者同名), 如果该远程分支不存在,则会被新建. git push origin master 表示将本地master分支推送到origin仓库的master分支 2. 如果省略本地分支名, 则表示删除远程分支,因为这等同于推送一个空的本地分支到远程分支 git push origin :master 3. 如果当前分支与远程分支存在追踪关系,则本地分支和远程分支都可以省略 git push origin 4. 如果当前分支只有一个追踪分支,那么主机名也可以省略 git push 5. 如果当前分支与多个主机存在追终关系,则可以使用-u指定一个默认主机(set upstream), 这样之后就可以不加任何参数使用git push了 git push -u origin master 本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了 不带任何参数的git push,默认只推送当前分支,这叫做simple方式。 此外,还有一种matching方式,会推送所有有对应的远程分支的本地分支。 Git 2.0版本之前,默认采用matching方法,现在改为默认采用simple方式。 如果要修改这个设置,可以采用git config命令。 - git config –global push.default matching
- git config –global push.default simple ## 创建远程分支 git push 远程仓库名 本地分支名:远程分支名 例: 首先创建一个本地分支: git checkout -b frommaster 以master为源创建分支frommaster git push origin frommaster:frommaster 因为远程创库中不存在frommaster分支,所以会创建这个分支
删除远程分支
git push 远程仓库名 (本地分支名为空):远程分支名
例:
git push :DX_A20_CDR_V1.1 将删除远程分支DX_A20_CDR_V1.1
查看远程分支
git branch -a
例如:
$ git branch -a * DX_A20_CDR_V1.1 a20-cdr-stable remotes/origin/DX_A20_CDR_V1.1 remotes/origin/HEAD -> origin/a20-cdr-stable remotes/origin/a20-cdr-stable
镜像仓库
例如已经有一个仓库位于: 192.168.3.175:/home/extend/A20linuxrepo/A20CDRV1.1/camdroid.git/
现在需要建立一个镜像仓库与上面的仓库同步,
git clone --mirror caodan_1@192.168.3.175:/home/extend/A20_linux_repo/A20_CDR_V1.1/camdroid.git/ 就会在当前目录建立一个镜像仓库camdroid.git
更新镜像仓库:
进入camdroid.git目录, 执行 git remote update
.gitignore设置忽略文件
使用.gitignore文件可以设置忽略的文件 如果在已经提交之后再设置.gitignore 需要使用 git rm –cached 命令删除缓存
例:
*.ko out .patch .ycm_extra_conf.py .ycm_extra_conf.pyc *.IAB *.IAD *.IMB *.IMD *.PFI *.PO *.PR *.PRI *.PS *.SearchResults *.WK3 cscope.* tags # # git files that we don't want to ignore # !app/newcdr/tools/MultiLingual/out
在前面加上感叹号!
表示不希望忽略的文件
分支管理
http://kb.cnblogs.com/page/132209/
git传输数据的几种协议
Git 可以使用四种主要的协议来传输数据:本地传输,SSH 协议,Git 协议和 HTTP 协议. 除了 HTTP 协议外,其他所有协议都要求在服务器端安装并运行 Git。
本地协议
最基本的就是本地协议(Local protocol),所谓的远程仓库在该协议中的表示,就是硬盘上的另一个目录。 这常见于团队每一个成员都对一个共享的文件系统(例如 NFS)拥有访问权 如果你使用一个共享的文件系统,就可以在一个本地文件系统中克隆仓库,推送和获取。克隆的时候只需要将远程仓库的路径作为 URL 使用,比如下面这样: `git clone /opt/git/project.git` 或者 `git clone file:///opt/git/project.git` 如果在 URL 开头明确使用 file:// ,那么 Git 会以一种略微不同的方式运行。 如果你只给出路径,Git 会尝试使用硬链接或直接复制它所需要的文件。 如果使用了 file:// ,Git 会调用它平时通过网络来传输数据的工序,而这种方式的效率相对较低。 要添加一个本地仓库作为现有 Git 项目的远程仓库,可以这样做: `git remote add local_proj /opt/git/project.git`
ssh协议
Git 使用的传输协议中最常见的可能就是 SSH 了。 这是因为大多数环境已经支持通过 SSH 对服务器的访问 — 即便还没有,架设起来也很容易. SSH 也是唯一一个同时支持读写操作的网络协议。 另外两个网络协议(HTTP 和 Git)通常都是只读的,所以虽然二者对大多数人都可用,但执行写操作时还是需要 SSH。 SSH 同时也是一个验证授权的网络协议;而因为其普遍性,一般架设和使用都很容易。 通过 SSH 克隆一个 Git 仓库,你可以像下面这样给出 ssh:// 的 URL: `git clone ssh://user@server/project.git` 或者不指明某个协议 — 这时 Git 会默认使用 SSH : `git clone user@server:project.git`
优点:
首先,如果你想拥有对网络仓库的写权限,基本上不可能不使用 SSH。 其次,SSH 架设相对比较简单 — SSH 守护进程很常见,很多网络管理员都有一些使用经验,而且很多操作系统都自带了它或者相关的管理工具。 再次,通过 SSH 进行访问是安全的 — 所有数据传输都是加密和授权的。最后,和 Git 及本地协议一样,SSH 也很高效,会在传输之前尽可能压缩数据。
缺点:
SSH 的限制在于你不能通过它实现仓库的匿名访问。 即使仅为读取数据,人们也必须在能通过 SSH 访问主机的前提下才能访问仓库,这使得 SSH 不利于开源的项目。 如果你仅仅在公司网络里使用,SSH 可能是你唯一需要使用的协议。 如果想允许对项目的匿名只读访问,那么除了为自己推送而架设 SSH 协议之外,还需要支持其他协议以便他人访问读取。
ssh授权:
收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件, 把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。
使用rsa认证:
- 使用本地机器生成密钥
-t rsa 表示生成的密钥的类型是rsa -C “192.168.3.132” 表示coment
caodan@caodan-ubuntu:/opt/Repository$ ssh-keygen -t rsa -C "192.168.3.132" Generating public/private rsa key pair. Enter file in which to save the key (/home/caodan/.ssh/id_rsa): /opt/Repository/rsa/id_rsa Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /opt/Repository/rsa/id_rsa. Your public key has been saved in /opt/Repository/rsa/id_rsa.pub. The key fingerprint is: 0a:eb:87:e7:90:9b:d7:87:d8:57:a3:a8:54:bd:cf:ee 192.168.3.132 The key's randomart image is: +--[ RSA 2048]----+ | | | | | | | . | | . S . | | + o .o | | +.o+ o.o . | | ..== = +o | | +=o. o oE | +-----------------+
管理公钥:
如果团队很小,把每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys文件里就是可行的。如果团队有几百号人,就没法这么玩了,这时,可以用Gitosis来管理公钥。
git协议
这是一个包含在 Git 软件包中的特殊守护进程; 它会监听一个提供类似于 SSH 服务的特定端口(9418),而无需任何授权。 打算支持 Git 协议的仓库,需要先创建 git-daemon-export-ok 文件 — 它是协议进程提供仓库服务的必要条件 — 但除此之外该服务没有什么安全措施。要么所有人都能克隆 Git 仓库,要么谁也不能。这也意味着该协议通常不能用来进行推送。 你可以允许推送操作;然而由于没有授权机制,一旦允许该操作,网络上任何一个知道项目 URL 的人将都有推送权限。 Git 协议是现存最快的传输协议。如果你在提供一个有很大访问量的公共项目,或者一个不需要对读操作进行授权的庞大项目,架设一个 Git 守护进程来供应仓库是个不错的选择。它使用与 SSH 协议相同的数据传输机制,但省去了加密和授权的开销。
缺点
Git 协议消极的一面是缺少授权机制。用 Git 协议作为访问项目的唯一方法通常是不可取的。 一般的做法是,同时提供 SSH 接口,让几个开发者拥有推送(写)权限,其他人通过 git:// 拥有只读权限。 Git 协议可能也是最难架设的协议。它要求有单独的守护进程,需要定制 该协议还要求防火墙开放 9418 端口,而企业级防火墙一般不允许对这个非标准端口的访问。 大型企业级防火墙通常会封锁这个少见的端口。
= HTTP/HTTPS协议 =
最后还有 HTTP 协议。HTTP 或 HTTPS 协议的优美之处在于架设的简便性。 基本上,只需要把 Git 的裸仓库文件放在 HTTP 的根目录下,配置一个特定的 post-update 挂钩(hook)就可以搞定