Git 实用教程


Git实用教程 Vietor Liu 第 1 页 2009 年8 月30日 Git 实用教程 Vietor Liu (vietor.liu@gmail.com) http://www.vxwo.com Version:2009-8-30 1 Git 简介 众所周知,Git是作为 linux kernel的版本控制工具,其命名是将get 的 e改为i,意味“傻 瓜式”版本控制工具,但这只是自嘲而已。Git 的产生是因为开源社区最终与BitKeeper 的k 开发厂家的关系破裂,由 Linus 发起编写的开源版本控制工具。Linus 设计 Git 的时候非常 多的参考了 SVN 的设计;对于一些不清楚怎么处理的细节,他就按照 SVN 相反的方式去处 理。 Git 对二进制文件的管理没有什么改进,但对于源代码管理却是一场革命;在同时代的 “分布式”版本控制系统中始终保持领先的位置。由于历史原因其对 Win 的支持仅限在 cygwin 的实现上,造成 Google Code 最终选择 Mercurial 作为分布式版本控制工具,同时一 部分用户倾向使用 Mercurial;但现在这已经不是问题;笔者一直就在使用 msysgit +TortoiseGit 的组合,使用过程还算流畅。本文主要以命令行的方式来进行使用讲解。 本文以 1.6.4 版本为背景,基本上 1.6.x 版也适用。 2 Git 的优势 2.1 分布式开发 分布式 SCM 意味着你不是 "checkout" 源代码的最新版,而是 "clone" 整个代码库。 这意味着即使使用中央集中式的工作流,每一个用户都拥有一份主服务器的备份,每一份都 可以在主服务器当机或损坏时用来替换它。使用Git 便不存在单点故障了,除非只有一个点。 Git实用教程 Vietor Liu 第 2 页 2009 年8 月30日 分布式开发相较集中式开发最突出的就是本地存储。本地存储可以让你离线开发。离线 开发使你的开发场地不受限制(比如在火车上)可以建立分支、合并、提交、浏览项目历史 等,生产力相对较高。再想象一下现场调试的场景,就知道这有多酷了,调试完毕可以同步 到公司的主库中。 2.2 强大的分支管理 Git 的分支,是实际意义的开发分支。SVN 的分支,过多的转变成了项目分支或分支子 项目。除此之外 SVN 分支方式仅仅是将库 (repository) 复制到一个新的目录而已。Git 允许 你拥有多个完全独立的本地分支,创建、合并和删除这些分支仅需要几秒钟的时间。 这意味着你可以这样做: · 创建一个新分支尝试新的想法,提交几次,切换回原先的分支,应用一个 patch, 然后再切换至刚才实验中的新分支,将其合并。 · 一个分支用来存放将要发布的版本,另一个测试分支专门合并开发中的工作,其他 数个小分支存放日常开发工作。 · 为每一个开发中的新功能建立相应分支,这样便可以在这些分支中无缝切换,并在 某个功能开发完毕合并进主分支后删除相应分支。 · 创建一个分支来做实验,若发现行不通则直接删掉该分支;放弃这个分支,别人甚 至不知道它存在过(即使这期间你已经 push 了其他分支)。 Git实用教程 Vietor Liu 第 3 页 2009 年8 月30日 重要的是,当你向一个远程库 push 时,你无需 push 所有分支。你可以只共享一个分 支而不是全部。 这会推动大家尝试新想法而不用操心如何、何时合并或与他人共享。 使用其他系统,你也可以找到一些方法来做同样的事,但会困难的多而且极易出错。 Git 让 这个过程异常简单,而且当大部分开发者学习 Git 时,他们同时改变了他们的工作方式。 2.3 适合多种工作流 2.3.1SVN 式的工作流 集中式工作流是一种很常见的工作流,这对于那些从集中式系统迁移过来的人来说尤其 如此。如果你上次 pull 过后,已经有其他人进行了 push 操作,那么 Git 将不允许你直接 push; 所以这种所有开发者向同一台服务器 push 的集中式模型可以工作的很好。 2.3.2集成管理员工作流 另一种常见工作流是有一名集成管理员专门负责向 'blessed' 库提交,其他开发者复制 该库,push 到他们自己独立的库,随后请求集成管理员 pull 他们的修改。这是开源工程或 Git实用教程 Vietor Liu 第 4 页 2009 年8 月30日 GitHub 库中很常见的一种开发模式。 2.3.3司令官与副官工作流 对于规模更庞大的项目,你可以让开发者使用类似 Linux 内核开发的工作流,每一个 子系统都有专人(副官)负责合并与该子系统相关的修改。 另有一名整合者(司令官)只 从副官那里 pull ,然后 push 到 'blessed' 库,其他所有人则再从 'blessed' 库复制。 再次强调,对于工作流 Git 非常有弹性,你可以混合及选用任何适合你的工作流。 3 Git 安装 Linux 环境: (1) yum install git 或 apt-get install git 完成安装。需要注意的是,这些安装包的更 新并不紧跟 git 的最新版本发布。 (2) http://kernel.org/pub/software/scm/git/RPMS/下载最新版本安装。 Windows 环境: 下载 msysgit 完成安装。紧跟 git 的最新版本发布。 Git实用教程 Vietor Liu 第 5 页 2009 年8 月30日 4 Git 初使用 4.1 下载源代码库 git clone git://github.com/vietor/myel.git Initialized empty Git repository in /home/vietor/WorkDir/myel/.git/ remote: Counting objects: 18, done. remote: Compressing objects: 100% (17/17), done. remote: Total 18 (delta 7), reused 0 (delta0) Receiving objects: 100% (18/18),17.32 KiB,done. Resolving deltas: 100% (7/7), done. 操作完成后,在当前目录下产生myel 目录,里面就是所有的代码了,这个目录被称为“工 作区”。进入工作区,有一个“.git”目录,即是整个源码树。 进一步使用: 有些时候:只是需要用 Git 下载最新的源代码,而不需要将所有的提交历史全部下载下 来;跟踪开源项目的进展,而不想下载动辄几百 MB 的完整源码库(Android据说很庞大, 上 G 的大小)。git-clone 有一个选项“--depth ”能够解决上面的问题实现“浅拷贝”。 “--depth”的参数可以理解为“截至到最近几次提交”,从 1开始。 git clone --depth 1 git://github.com/vietor/myel.git Initialized empty Git repository in /home/vietor/WorkDir/myel/.git/ remote: Counting objects: 12, done. remote: Compressing objects: 100% (11/11), done. emote: Total 12 (delta 2), reused 0 (delta 0) Receiving objects: 100% (12/12),16.45 KiB,done. Resolving deltas: 100% (2/2), done. 很明显,比完全拷贝少了 6个对象。 4.2 查看修改日志 git log commit 1d50bd8a5a340c43782ba481af28c9a70fe219a2 Author: Vietor Liu Date: Thu Jul 23 14:06:30 2009 +0800 Add csvtool -i rows limit commit 2d66c1ea713083952efff1d3dbaef695420c4053 Author: Vietor Liu Date: Thu Jul 23 11:48:49 2009 +0800 Use packet Dic & Add csvtool Git实用教程 Vietor Liu 第 6 页 2009 年8 月30日 ...其他的 返回信息含义应该是很明显的。 git show HEAD commit 1d50bd8a5a340c43782ba481af28c9a70fe219a2 Author: Vietor Liu Date: Thu Jul 23 14:06:30 2009 +0800 Add csvtool -i rows limit diff --git a/COPYING b/COPYING old mode 100755 new mode 100644 diff --git a/csvtool.pl b/csvtool.pl index b521a36..7d53fbb 100755 --- a/csvtool.pl +++b/csvtool.pl @@ -24,13 +24,13 @@ my $dbname="myel.db"; subusage{ print "用法: csvtool usage\n"; - print " csvtool -i <文件>\n"; + print " csvtool -i <文件> [条数]\n"; print " csvtool -e <文件>\n"; exit(1); }; 返回信息是详细的修改日志,以 diff 格式显示文件差异。 逐次查看以前的详细修改日志,可以使用如下的命令: git show HEAD~1 (一次前) git show HEAD~2 (两次前) …… 提示:可以使用命令:gitk 以图形界面查看修改日志。 4.3 更新源代码 git pull Alreadyup-to-date. 从远程代码库更新本地代码库。可以追踪一些感兴趣的项目的开发过程。 Git实用教程 Vietor Liu 第 7 页 2009 年8 月30日 5 Git 本地版本控制 5.1 创建自己的库 mkdir test cd test git init Initialized empty Git repository in /home/vietor/WorkDir/test/.git/ 返回信息提示库已经创建成功了。 5.2 添加文件到库 echo t1 >test.txt git add test.txt git commit -m t1 [master (root-commit) c93a0b9] t1 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 test.txt 返回信息已经提示将文件添加到源码库中。git-add是将文件放入更新索引中,git-commit 完成最终的提交。git-add 以“.”作为参数,如:”git add .”表示当前目录下的所有文件都加入索 引(包括子目录)。git-commit 必须写“commit message”,使用-m选项可以指定。 进一步使用: 像其他 SCM 一样,git 也有一个忽略文件“.gitignore”。其语法支持模糊匹配,类似与 ls 与 dir 的匹配规则,一个普通的规则如下: *~ .* *.db *.swp *.exe test/* “.gitignore”文件的一个副作用就是可以帮助提交空目录。Git 不允许提交空目录,可以 在其下放一个“.gitignore”。 5.3 比较本地修改 echo t2>test.txt git diff diff --git a/test.txt b/test.txt index 795ea43..9bc7ad0 100644 Git实用教程 Vietor Liu 第 8 页 2009 年8 月30日 --- a/test.txt +++b/test.txt @@ -1 +1 @@ -t1 +t2 返回信息以 diff 格式显示文件差异。 5.4 将修改提交 方式一: git add test.txt git commit -m t2 方式二: git commit -a -m t2 返回信息两种方式相同: [master 212de73] t2 1 files changed, 1 insertions(+), 1 deletions(-) 方式二中的参数-a,表示把已经在源码库中的文件不需要加入更新索引直接进行提交。 5.5 将修改回滚 echo t0>test.txt 方式一: git checkout test.txt 方式二: git reset --hard HEAD is now at 212de73 t2 方式一,将单一的文件进行回滚;方式二,将整个工作区进行回滚。方式二还支持将已 经提交的内容进行回滚,可以使用如下的命令: git reset --hard HEAD~1 (一次前) git reset --hard HEAD~2 (两次前) git-reset 的回滚方式将日志进行了回滚,这种回滚不能够被恢复,谨慎使用。 5.6 分支管理 Git 最据优势的功能就是分支管理。 5.6.1创建分支 git branch develop git branch Git实用教程 Vietor Liu 第 9 页 2009 年8 月30日 develop * master 创建一个分支develop;Git 默认有一个主分支 master。git-branch显示所有分支的列表, 当前的分支前面有一个“*”。 5.6.2切换分支 git checkout develop Switched to branch 'develop' git branch * develop master 分支切换时,工作区内的文件也会发生变化。 5.6.3合并分支 echo t3>test.txt git commit -a -m t3 [developb11f6a1] t3 1 files changed, 1 insertions(+), 1 deletions(-) 返回结果显示,修改已经被提交到到了 develop 分支中。 git checkout master Switched to branch 'master' git mer ge develop Updating 212de73..b11f6a1 Fast forward test.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) 返回结果显示,已经将开发分支中的变更合并到主分支中。 提示:使用 gitk 图形界面能够对此处的理解非常有帮助。 5.6.4删除分支 git branch -d develop Deleted branch develop (was b11f6a1). 分支被删除了。 5.7 标签操作 git tag v1.0.0 创建名为 v1.0.0 的标签 Git实用教程 Vietor Liu 第 10 页 2009 年8 月30日 git tag -d v1.0.0 删除名为 v1.0.0 的标签 进一步使用: git 的标签与分支截然不同,想取分支的数据必须以标签为基础创建一个分支。 git branch b1.0.0 v1.0.0 以 v1.0.0为基础创建分支 b1.0.0。 6 简单 GitHub 教程 6.1 创建 SSH-KEY ssh-keygen -t r sa Generating public/private rsa key pair. Enter file in which to save the key (/home/vietor/.ssh/id_rsa): .....直接回车 Created directory '/home/vietor/.ssh'. Enterpassphrase (empty for no passphrase): .....直接回车 Entersame passphrase again: .....直接回车 Your identification has been saved in /home/vietor/.ssh/id_rsa. Your public key has been saved in /home/vietor/.ssh/id_rsa.pub. The key fingerprint is: 24:db:e4:b4:35:3d:a8:fd:15:bc:5f:0a:18:c3:b0:f0 vietor@localhost.localdomain The key's randomart image is: +--[ RSA 2048]----+ | . . | | o + o . | | . E B oo | | O = = .o | | . S o .o .| | . o o.| | . . .| | | | | +-----------------+ 其中“passphrase”是这个 SSH-key 的密码和用户的密码无关,主要在使用ssh-key 的时候 让你输入进行认证用的,可以不使用免去每次都输密码的麻烦。 程序最终生成两个文件id_rsa(私钥)、id_rsa.pub(公钥);id_rsa.pub的内容即是“SSH Public Key”。 cat ~/.ssh/id_r sa.pub Git实用教程 Vietor Liu 第 11 页 2009 年8 月30日 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAA…… 6.2 在 GitHub 上注册帐号 不进行描述了,注册帐号是需要输入“SSH Public Key”,,就是上边的 id_rsa.pub文件内 容。 登录 Github系统后,进入“account”设置,需要按“Your User Information”的内容进行设置; 点击“Global GitConfig”将提示命令行,本地执行即可。 6.3 将一个本地项目上传 创建一个项目后,GitHub将有提示信息,提示信息如下: Global setup: Download and install Git git config --global user.name "Vietor Liu" git config --global user.email vietor.liu@gmail.com Next steps: mkdir test cd test git init touch README git add README git commit -m 'first commit' git remote add origin git@github.com:vietor/test.git git push origin master Existing Git Repo? cd existing_git_repo git remote add origin git@github.com:vietor/test.git git push origin master GitHub的提示信息基本已经简要的介绍了 git push 的使用。git-push 主要是将本地的 源码库同步到远端。 提示:git-push 使用--tags 参数可以将本地标签同步到远程库。 Git实用教程 Vietor Liu 第 12 页 2009 年8 月30日 7 Git 功能进阶 7.1 源码库维护 7.1.1垃圾文件清理 git clean -dfx Removingmyel.db Removingyum.log 返回结果显示了清理的文件列表。如果只是想知道那些文件将被清理而不实际的清理文 件则命令为:git clean -dnx。这种清理方式一般可代替 make clean的操作。 7.1.2源码库压缩 git gc Counting objects: 20, done. Compressing objects: 100% (19/19), done. Writing objects: 100% (20/20),done. Total 20 (delta 9), reused 0 (delta 0) Git 所有的文件都是以ZLIB的压缩方式存放的,采用HASH 目录的存放方式,通过git-gc 命令可以让 Git 合并为一个文件,进一步压缩库大小。 7.1.3导出干净代码 git archive --for mat=zip HEAD >tmp.zip 将源码对象的数据打包成 zip 文件。 git archive --for mat=tar HEAD|gzip >tmp.tar .gz 将源码对象的数据打包成 tar.gz 文件。 提示:其中 HEAD 可以替换成标签名、分支名。 7.2 源代码发布 7.2.1patch 文件 git diff HEAD HEAD~1 >temp.patch path 的制作是 git-diff 命令的副产品,只需要将 git-diff 的输出重定向为文件即可。其中 git-diff 的参数可以是两次提交也可以是两个分支,详见 git help diff。 Git实用教程 Vietor Liu 第 13 页 2009 年8 月30日 7.2.2源码库共享 主要用于两个开发者间做代码审查(CodeReview)的情况。 提供者: git daemon --expor t-all --base-path=/home/a/r epos/test 读取者: git clone git://xxx.xxx.xxx.xxx/.git test 提供者用--bash-path指定的是起工作目录,读取者将完整克隆提供者提供的 test 的库。 7.3 远程分支管理 首先要强调 Git 克隆的是整个源码库,包括远程服务器上的分支与标签。严格意义上没 有远程分支的概念,只是怎样本地与远程库进行同一分支的同步的问题。本文仍使用远程分 支来表述远程库同一分支的概念。 7.3.1创建远程分支 git branch develop git push or igin develop Total 0 (delta0), reused 0 (delta 0) To git@github.com:vietor/myel.git * [new branch] develop -> develop 返回结果显示,远程分支的创建,只是将本地分支的创建进行了一次同步过程。 提示:若本地分支修改了,可通过 git-push 命令将其同步到远程分支上。 7.3.2删除远程分支 git branch -D develop Deleted branch develop (was 01ce4e9). git push :heads/develop To git@github.com:vietor/myel.git - [deleted] develop 首先通过-D 参数来删除本地分支,后同步远程服务器以删除远程分支。 7.4 使用 HTTP 代理 Git 支持的网络连接方式有三种:git-daemon,ssh,http/https。由于历史原因,互联网 的 Git 服务器使用 git-daemon与 http/https 支持 pull,ssh支持 pull 与 push。 部分公司的网络防火墙端口限制比较严格,上网只能使用 HTTP 代理。好在 git 是通过 管道执行ssh来实现文件传输的,直接解决了ssh使用 HTTP 代理就行了。我们借助一个 Perl Git实用教程 Vietor Liu 第 14 页 2009 年8 月30日 脚本 ssh-https-tunnel(在附件中),将其放到你的.ssh 目录中。 Perl 脚本 ssh-https-tunnel 发送 CONNNET 请求到你的代理服务器,指示它打开一个 到远程主机端口的 TCP 连接。然后它允许你通过标准输入/标准输出和这个端口通讯。 1. 更新你的 ~/.ssh/config 文件 Host www.example.com ProxyCommand ~/.ssh/ssh-https-tunnel %h %p 2. 把你的代理服务设置放在 ssh-https-tunnel 文件中 ####Configuration #### my $proxy = "my-proxy.company.com"; my $proxy_port = 80; 3.可能遇到的问题 a)Linux 环境下 config文件的属性必须为 644,ssh-https-tunnel 必须有执行属性。 chmod 644 config chmod +x ssh-https-tunnel b)msysgit 环境下无权限问题,同时有完整的 perl 与 tcl 环境。 8 Gitosis 权限管理 Gitosis 主要用于设置源代码服务器时使用。Git 源代码服务器,必须安装有 Git。 8.1 下载安装 gitosis git clone git://eagain.net/gitosis.git cd gitosis python setup.py install 8.2 创建管理用户 useradd git #无密码不可登录 su git cd ssh-keygen -t rsa #按提示生成 gitosis-init < .ssh/id_rsa.pub 8.3 开始管理仓库 1)在 git 下新建 manager 目录 cd manager 2)通过 git 来完成 gitosis 的设置 git clone git@localhost:gitosis-admin (1)通过向目录 keydir 中添加 SSH-KEY 来标识用户 Git实用教程 Vietor Liu 第 15 页 2009 年8 月30日 ls keydir/ git@localhost.localdomain.pub lidj.pub liulei.pub (2)通过修改 gitosis.conf 来管理用户的权限 cat gitosis.conf [gitosis] [group gitosis-admin] writable = gitosis-admin members = git@localhost.localdomain [group test] writable = test.git members = liulei lidj [group t11] writable = t11/t11web members = liulei lidj [group t12] writable = t12/t12web members = liulei lidj 3)一般使用 (1)在.ssh目录中保证有正确的私钥 (2)git clone git@127.0.0.1:test.git 9 参考 《Why Git is Better than X》 http://zh-cn.whygitisbetterthanx.com/ 《透过 HTTP 代理服务访问 ssh 服务》 http://www.mamiyami.com/neo-diary/2007/07/ssh-via-https-proxy.html 10 附件 10.1 ssh-https-tunnel #!/usr/bin/perl -w # -*- perl -*- Git实用教程 Vietor Liu 第 16 页 2009 年8 月30日 # # (c) 1999 Chris Chiappa # This code is released to the public domain. I take no responsibility # for anything done with it. It is supplied without any warranty. # # V1.1 # V1.0 6/13/1999 # # $Id: stunnel,v 1.2 2000/03/07 20:21:23 griffon Exp $ # ##################################################################### ## # Proxy through an https tunnel. sshd probably needs to be running on # port 443 unless the proxy is very lenient. # You should add an entry to your .ssh/config such as the following: # # host remote.host.com # ProxyCommand /home/user/bin/stunnel %h %p # Port 443 # # Thereafter 'ssh remote.host.com' will use this program to tunnel # through the firewall to the remote host. # # You may need to tweak it a little to cope with the peculiarities # of your firewall. ##################################################################### ## use strict; use Socket; use FileHandle; #### Configuration #### my $proxy = "my-proxy.company.com"; my $proxy_port = 80; ################################################################# my ($rem_host, $rem_port) = ($ARGV[0], $ARGV[1]); $| = 1; Git实用教程 Vietor Liu 第 17 页 2009 年8 月30日 $rem_host || die "Remote host not supplied"; $rem_port || die "Remote port not supplied"; my $pSOCK = proxy_connect(); $pSOCK || die "Couldn't connect to proxy!"; my $SOCK = $$pSOCK; # These hashes hold the source and destination file handles for the # file numbers we use in select() my (%rfds, %wfds); my ($stdin_fileno, $sock_fileno) = (fileno(*STDIN), fileno($SOCK)); $rfds{$stdin_fileno} = \*STDIN; $rfds{$sock_fileno} = $SOCK; $wfds{$stdin_fileno} = $SOCK; $wfds{$sock_fileno} = \*STDOUT; $SOCK->print("CONNECT $rem_host:$rem_port HTTP/1.0\n\n"); SCANHEADERS: while(<$SOCK>) { /^\s+$/ && last SCANHEADERS; } #(! m,^HTTP/1.. 2.. Connection established,) && # die "Unexpected response from firewall: $_"; # Set up for select my $rin = ""; vec($rin, $stdin_fileno, 1) = 1; vec($rin, $sock_fileno, 1) = 1; my $ein = $rin; my ($rout, $eout); # Loop, reading from one socket and writing to the other like a good # proxy program SELECT: while(1) { my $nfound = select($rout = $rin, undef, $eout = $ein, 1024); $nfound || next SELECT; (vec($eout, $stdin_fileno, 1) || vec($eout, $sock_fileno, 1)) && last SELECT; foreach my $key (keys(%rfds)) { Git实用教程 Vietor Liu 第 18 页 2009 年8 月30日 if(vec($rout, $key, 1)) { do_copy($rfds{$key}, $wfds{$key}) || last SELECT; } } # next SELECT; } $SOCK->close(); exit(0); ##################################################################### ## # Copy stuff from one filehandle to another sub do_copy { my($pIn, $pOut) = @_; my ($buf, $len, $offset, $br); $len = sysread($$pIn, $buf, 1024); $len || return 0; $offset = 0; while($len) { $br = syswrite($$pOut, $buf, $len, $offset); $br || return 0; $offset += $br; $len -= $br; } return 1; } # Connect to the proxy and return a filehandle for it. sub proxy_connect { my $iaddr = inet_aton($proxy); my $paddr = sockaddr_in($proxy_port, $iaddr); my $proto = getprotobyname('tcp'); my $fh = new FileHandle; socket($fh, PF_INET, SOCK_STREAM, $proto) or return; connect($fh, $paddr) or return; $fh->autoflush(1); return \$fh; Git实用教程 Vietor Liu 第 19 页 2009 年8 月30日 } 注: 1) git-add表示命令“git add”。文中以加“-”的方式来减少双引号的使用,并不是提倡带 “-”命令的使用。在 1.5版本以前全部命令使用带“-”的方式,1.5之后不建议使用了。 2) 文中部分--显示存在问题,主要是字体造成的。
还剩18页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 15 金币 [ 分享pdf获得金币 ] 2 人已下载

下载pdf

pdf贡献者

liujiuwu

贡献于2012-09-03

下载需要 15 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf