blog:linux_system_manage:git

git使用说明

正确的版本控制系统的使用方法是: 一次提交只干一件事, 或者完成一个新的功能, 或者是修改了一个Bug

install and configure

  1. sudo apt-get install git-core
  2. sudo apt-get install openssh-server
  3. sudo apt-get install openssh-client
  4. sudo service ssh start
  1. 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的三个配置文件分别是:

  • 版本库级别的配置文件(.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 [path]		添加指定的文件到暂存区
git add -u [path]	将path中所有tracked文件中被修改过或者已删除文件的信息添加到暂存区,
                    但不会处理untracked的文件
git add -A [path]	把path中所有tracked文件中被修改过或已删除文件和所有untracted的文件
                    信息添加到暂存区
  • 修改本次提交的commit
    git commit –amend 修改之前的提交comment
  1. 工作空间与暂存区进行比较
    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
  2. 比较两个版本的变化,只显示文件名
    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`
	
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 软件包中的特殊守护进程; 它会监听一个提供类似于 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)就可以搞定
  • blog/linux_system_manage/git.txt
  • 最后更改: 2022/01/09 22:58
  • 127.0.0.1