Tag: git
小组级git服务器搭建
by Elton on 十一.26, 2009, under Linux
如果使用git的人数较少,可以使用下面的步骤快速部署一个git服务器环境。
1. 生成 SSH 公钥
每个需要使用git服务器的工程师,自己需要生成一个ssh公钥
进入自己的~/.ssh目录,看有没有用 文件名 和 文件名.pub 来命名的一对文件,这个 文件名 通常是 id_dsa 或者 id_rsa。 .pub 文件是公钥,另一个文件是密钥。假如没有这些文件(或者干脆连 .ssh 目录都没有),你可以用 ssh-keygen 的程序来建立它们,该程序在 Linux/Mac 系统由 SSH 包提供, 在 Windows 上则包含在 MSysGit 包里:
1 2 3 4 5 6 7 8 9 | $ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/Users/schacon/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /Users/schacon/.ssh/id_rsa. Your public key has been saved in /Users/schacon/.ssh/id_rsa.pub. The key fingerprint is: 43:c5:5b:5f:b1:f1:50:43:ad:20:a6:92:6a:1f:9a:3a schacon@agadorlaptop.local |
它先要求你确认保存公钥的位置(.ssh/id_rsa),然后它会让你重复一个密码两次,如果不想在使用公钥的时候输入密码,可以留空。
现在,所有做过这一步的用户都得把它们的公钥给你或者 Git 服务器的管理者(假设 SSH 服务被设定为使用公钥机制)。他们只需要复制 .pub 文件的内容然后 e-email 之。公钥的样子大致如下:
1 2 3 4 5 6 7 | $ cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3 Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx NrRFi9wrf+M7Q== schacon@agadorlaptop.local |
2. 架设服务器
首先,创建一个 ‘git’ 用户并为其创建一个 .ssh 目录,在用户主目录下:
1 2 3 4 | $ sudo adduser git $ su git $ cd $ mkdir .ssh |
接下来,把开发者的 SSH 公钥添加到这个用户的 authorized_keys 文件中。假设你通过 e-mail 收到了几个公钥并存到了临时文件里。只要把它们加入 authorized_keys 文件
1 2 3 | $ cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys $ cat /tmp/id_rsa.josie.pub >> ~/.ssh/authorized_keys $ cat /tmp/id_rsa.jessica.pub >> ~/.ssh/authorized_keys |
现在可以使用 –bare 选项运行 git init 来设定一个空仓库,这会初始化一个不包含工作目录的仓库。
1 2 3 4 | $ cd /opt/git $ mkdir project.git $ cd project.git $ git --bare init |
这时,开发人员就可以把它加为远程仓库,推送一个分支,从而把第一个版本的工程上传到仓库里了。值得注意的是,每次添加一个新项目都需要通过 shell 登入主机并创建一个纯仓库。我们不妨以 gitserver 作为 git 用户和仓库所在的主机名。如果你在网络内部运行该主机,并且在 DNS 中设定 gitserver 指向该主机,那么以下这些命令都是可用的:
1 2 3 4 5 6 7 | # 在一个工程师的电脑上 $ cd myproject $ git init $ git add . $ git commit -m 'initial commit' $ git remote add origin git@gitserver:/opt/git/project.git $ git push origin master |
这样,其他人的克隆和推送也一样变得很简单:
1 2 3 4 | $ git clone git@gitserver:/opt/git/project.git $ vim README $ git commit -am 'fix for the README file' $ git push origin master |
用这个方法可以很快捷的为少数几个开发者架设一个可读写的 Git 服务。
作为一个额外的防范措施,你可以用 Git 自带的 git-shell 简单工具来把 git 用户的活动限制在仅与 Git 相关。把它设为 git 用户登入的 shell,那么该用户就不能拥有主机正常的 shell 访问权。为了实现这一点,需要指明用户的登入shell 是 git-shell ,而不是 bash 或者 csh。你可能得编辑 /etc/passwd 文件
1 | $ sudo vim /etc/passwd |
在文件末尾,你应该能找到类似这样的行:
1 | git:x:1000:1000::/home/git:/bin/sh |
把 bin/sh 改为 /usr/bin/git-shell (或者用 which git-shell 查看它的位置)。该行修改后的样子如下:
1 | git:x:1000:1000::/home/git:/usr/bin/git-shell |
现在 git 用户只能用 SSH 连接来推送和获取 Git 仓库,而不能直接使用主机 shell。尝试登录的话,你会看到下面这样的拒绝信息:
1 2 3 | $ ssh git@gitserver fatal: What do you think I am? A shell? (你以为我是个啥?shell吗?) Connection to gitserver closed. (gitserver 连接已断开。) |
Git与Xcode配合使用
by Elton on 十.07, 2009, under Mac
要想使Git与Xcode配合使用,就需要设置好以下两个文件。
在项目根目录下加入如下两个文件:
1. gitignore
1 2 3 4 5 6 7 8 9 10 11 | # xcode noise build/* *.pbxuser *.mode1v3 # old skool .svn # osx noise .DS_Store profile |
2. .gitattributes
1 | *.pbxproj -crlf -diff -merge |
这行是将xcode的项目文江当作二进制文件来处理,这样就不会随意添加比较信息等git的信息了。
Git学习笔记(7) — 独立开发者所用的命令(c)
by Elton on 七.22, 2009, under Linux
这次我们看一些实例
Use a tarball as a starting point for a new repository.
1 2 3 4 5 6 | $ tar zxf frotz.tar.gz $ cd frotz $ git init $ git add . //添加所有文件到index $ git commit -m "import of frotz source tree." $ git tag v2.43 |
Create a topic branch and develop.
$ git checkout -b alsa-audio (1)
$ edit/compile/test
$ git checkout -- curses/ux_audio_oss.c (2)
$ git add curses/ux_audio_alsa.c (3)
$ edit/compile/test
$ git diff HEAD (4)
$ git commit -a -s (5)
$ edit/compile/test
$ git reset --soft HEAD^ (6)
$ edit/compile/test
$ git diff ORIG_HEAD (7)
$ git commit -a -c ORIG_HEAD (8)
$ git checkout master (9)
$ git merge alsa-audio (10)
$ git log --since='3 days ago' (11)
$ git log v2.43.. curses/ (12)
- create a new topic branch.
- revert your botched changes in curses/ux_audio_oss.c.
- you need to tell git if you added a new file; removal and modification will be caught if you do git commit -a later.
- to see what changes you are committing.
- commit everything as you have tested, with your sign-off.
- take the last commit back, keeping what is in the working tree.
- look at the changes since the premature commit we took back.
- redo the commit undone in the previous step, using the message you originally wrote.
- switch to the master branch.
- merge a topic branch into your master branch.
- review commit logs; other forms to limit output can be combined and include –max-count=10 (show 10 commits), –until=2005-12-10, etc.
- view only the changes that touch what’s in curses/ directory, since v2.43 tag.
Git学习笔记(6) — 独立开发者所用的命令(b)
by Elton on 七.22, 2009, under Linux
git commit 将当前在index中变化的内容提交到仓库(repository)中
语法:
1 | git commit [-a | --interactive] [-s] [-v] [-u] [--amend] [(-c | -C) ] [-F | -m ] [--allow-empty] [--no-verify] [-e] [--author=] [--cleanup=] [--] [[-i | -o ]…] |
- 使用git add命令可以持续的将变动或者新增的内容添加到index中。
- 使用git rm 可以将文件从woking tree和index中移除。
- 作为参数列在后面的文件,将忽略在index中的变化,而直接使用当前的内容作为提交内容。(例如你之前add过这个文件,但是在add后,又修改过且没有再次add)
- 使用-a参数就自动将所有变化的文件执行add操作(这些文件曾经都被add到index中),并将所有在working tree中移除的文件从Index中移除,之后再进行commit
git-reset 重置当前HEAD到指定的状态
适合与你发现刚才作的一些操作是错误的,要Undo一些操作
语法:
1 2 | git reset [--mixed | --soft | --hard | --merge] [-q] [<commit>] git reset [-q] [<commit>] [--] <paths>… |
–soft,表示不变更working tree和index
–hard,表示working tree和index一同变更
例子:
Undo一个commit再Redo
1 2 3 4 | $ git commit ... $ git reset --soft HEAD^ 回退到上一次commit,并不改变workingtree和index 编辑一些内容 $ git commit -a -c ORIG_HEAD 再次按照原来的HEAD的注释提交,-c表示使用原来的commit时候的注释 |
永久的回退
1 2 | $ git commit ... $ git reset --hard HEAD~3 //永久删掉HEAD,HEAD^和HEAD~2三个版本 |
git checkout 切换当前分支
git checkout
git checkout -b
git checkout -b
git checkout v2.3 将当前HEAD从现有分支上解除,直接指向新的tag版本 1.5以后支持。
例子:
切换分支到master,将Makefile文件回退两个版本,错误删除了hello.c,再从index中恢复
1 2 3 4 | $ git checkout master (1) $ git checkout master~2 Makefile (2) $ rm -f hello.c $ git checkout -- hello.c (3) |
Git学习笔记(5) — 独立开发者所用的命令(a)
by Elton on 七.22, 2009, under Linux
独立开发者的最大特点就是他们不需要和其他人来交换补丁,而且只在一个独立的固定的git仓库中工作。
下面这些命令将可以帮助你完成日常工作:
git-show-branch:可以显示你当前所在的分支以及提交记录。
git-log:显示提交日志
git-checkout或者git-branch:用于切换和创建分支
git-add:用于将修改内容加入到index文件中
git-diff和git-status:用于显示开发者所做的修改
git-commit:用于提交当前修改到git仓库。
git-reset和git-checkout:用于撤销某些修改
git-merge:用于合并两个分支
git-rebase:用于维护topic分支(此处我也不太懂,等完成git学习后转过头来会关注此问题)
git-tag:用于标记标签。
git checkout 命令格式
1 2 3 | git checkout [-q] [-f] [-m] [<branch>] git checkout [-q] [-f] [-m] [-b <new_branch>] [<start_point>] git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>… |
git checkout
git checkouot -b
git checkout v2.6.18 切换到v2.6.18这个tag的start_point上, 1.5以后的git支持
下面的代码切换到master分支,后退Makefile两个版本,错误的删除了 hello.c , 然后再从index恢复它.
1 2 3 4 | $ git checkout master $ git checkout master~2 Makefile $ rm -f hello.c $ git checkout -- hello.c |
git branch 显示,新建和删除分支
命令格式:
1 2 3 | git branch [--color | --no-color] [-r | -a] [-v [--abbrev=<length> | --no-abbrev]] [(--merged | --no-merged | --contains) [<commit>]] git branch [--track | --no-track] [-l] [-f] <branchname> [<start-point>] git branch (-m | -M) [<oldbranch>] <newbranch> git branch (-d | -D) [-r] <branchname>… |
git branch ,不带任何参数就是显示所有的本地分支。 带上-r参数,表示显示远程分支。 -a表示远程分支和本地分支都要
git branch
例子:
从一个版本创建分支
1 2 3 4 | $ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6 $ cd my2.6 $ git branch my2.6.14 v2.6.14 //前面一个参数是branch名,后面是指定的tag名,从这个版本创建分支 $ git checkout my2.6.14 //这两步可以合并为一步:"checkout -b my2.6.14 v2.6.14" |
git add 命令用于把修改过的文件或者新的文件加入到index中
这个命令可以在commit前执行多次。 可以利用git status来查看那些文件被add到index中,下次commit的时候会提交。
例子:
添加所有目录Documentation(包括Documentation子目录)下的.txt文件
1 | $ git add Documentation/\*.txt |
添加所有git-*.sh脚本,子目录下的文件不会被add。 如subDir/git=foo.sh
1 | $ git add git-*.sh |
Git学习笔记(4) — 基本命令
by Elton on 七.22, 2009, under Linux
git init
初始化一个本地目录,加入版本管理
git clone
克隆一个版本库(repository)到一个新的目录
命令格式
1 | git clone [--template=<template_directory>] [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror] [-o <name>] [-u <upload-pack>] [--reference <repository>] [--depth <depth>] [--] <repository> [<directory>] |
在clone后, 执行不带参数的git fetch的命令将更新远端的任何branches, 而执行不带参数的git pull的命令将merge远程的master branch到当前master branch
rsync://host.xz/path/to/repo.git/
http://host.xz[:port]/path/to/repo.git/
https://host.xz[:port]/path/to/repo.git/
git://host.xz[:port]/path/to/repo.git/
git://host.xz[:port]/~user/path/to/repo.git/
ssh://[user@]host.xz[:port]/path/to/repo.git/
ssh://[user@]host.xz/path/to/repo.git/
ssh://[user@]host.xz/~user/path/to/repo.git/
ssh://[user@]host.xz/~/path/to/repo.git
其中ssh是默认协议,所以如果使用ssh协议可以不写ssh的协议名
如果使用本地仓库,可以使用以下路径:
/path/to/repo.git/
file:///path/to/repo.git/
使用以上仓库路径,就相当于显式的使用了-l或-local参数
Git学习笔记(3) — 标记(tag)
by Elton on 七.22, 2009, under Linux
当执行git log
1 2 3 4 5 | $ git log <strong>commit 29293409f6d4a389fee75bd42fba5194fee5b899</strong> Author: elton <elton.zheng.sh@gmail.com> Date: Wed Jul 22 12:26:11 2009 +0800 ... |
其中commit后面的数字是一个唯一的版本号,每次提交都不同。
显示版本信息
1 | $git show 29293409f6d4a389fee75bd42fba5194fee5b899 |
就显示这个版本的详细信息
也可以使用
1 | $git show 292934 |
只要你这个版本号足够区分其他版本就可以了。
1 | $git show master |
显示master分支的版本信息
1 | $git show HEAD |
HEAD代表当前分支的头(也就是最近一次commit)
每一次commit都会有”parent commit”,可以使用^表示parent:
1 2 3 4 5 6 7 | $git show HEAD^ //查看HEAD的父母的信息 $git show HEAD^^ //查看HEAD的父母的父母的信息 $git show HEAD~4 //查看HEAD上溯4代的信息 要注意的是git-merge是会产生双父母的,这种情况这样处理: $git show HEAD^1 //查看HEAD的第一个父母 $git show HEAD^2 //查看HEAD的第二个父母 |
当你觉得某个版本是一个有意义的里程碑的时候,你可以为这个版本打一个标记
1 | $git tag V3 5b888 |
这样就给5b888这个版本打了一个tag,之后就可以使用这个版本来作其他的操作了
如显示详情
1 | $git show V3 |
创建一个基于V3的分支
1 | $ git branch stable V3 |
Git学习笔记(2) — 分支控制(branch)
by Elton on 七.22, 2009, under Linux
git branch
列出所有的分支, -r参数表示列出所有远程的分支
git branch
建立一个名为
git branch
建立一个名为
git branch -d
删除分支
git branch -D
同-d,但是不管要删除的分支是否已经merge到当前分支,都会删除
git checkout
切换当前分支到
git checkout -b
按照
一个特殊符号 “HEAD” 总是指向当前分支. 实际上git使用一个在.git目录中叫 “HEAD”的文件来记录当前分支:
1 2 | $ cat .git/HEAD ref: refs/heads/master |
示例:
“master”分支是当初你执行git-clone时候,clone的一个远程repository的HEAD版本的一个copy.
1 2 3 4 5 6 7 8 9 | $ git branch -r origin/HEAD origin/html origin/maint origin/man origin/master origin/next origin/pu origin/todo |
列出所有远程版本, origin是用来表示你当初执行git-clone时候的repository,你不可以直接checkout远程repository,但是你可以根据远程repository生成一个本地repository
1 | $ git checkout -b my-todo-copy origin/todo |
Git学习笔记(1) — 创建和修改项目
by Elton on 七.22, 2009, under Linux
当你设置好gitosis(使用gitosis来配置管理git服务器端)后,就可以使用git来管理你的项目了。
当新创建一个项目的时候,需要在gitosis的gitosis.conf文件中添加对应的项目
1 2 3 4 5 6 | # cd gitosis-admin # vim gitosis.conf 添加: [group myteam] #team名称 members = elton@macbook #开发者名称 writable = project_name #项目名称,表示members中的开发者对这个项目可写 |
之后,进入你这个项目的目录,执行以下命令
1 2 | $ cd your_project $ git remote add origin git@YOUR_SERVER_HOSTNAME:project_name.git |
其中project_name.git中的project_name跟gitosis.conf中的项目名称一样。添加远程repo
初始化项目
1 | git init |
git init命令用于初始化当前所在目录的这个项目,shell返回的提示表明已经建立了一个.git隐藏目录来保存这个项目目前的进展信息。我们可以用ls -a看到它。
添加文件到git index
1 | git add . |
git add .这个命令要求git给我目前的这个项目制作一个快照snapshot(快照只是登记留名,快照不等于记录在案,git管快照叫做索引index)。快照一般会暂时存储在一个临时存储区域中。
提交
1 | git commit -m "init the project" |
git commit用于将快照里登记的内容永久写入git仓库中,也就是开发者已经想好了要提交自己的开发成果了。
查找更改
1 2 | git diff –cached git diff |
git diff –cached是用来查看index file(快照)和仓库之间代码的区别的。
git diff 是比较working tree和index file(快照)的区别,working tree就是表示你的源文件
当你修改过源代码后,但是没有commit的时候,git diff –cached是没有输出结果的,但是git diff有结果,列出了源文件和index之间的差别。 当你提交后,git diff –cached就有输出结果了,而git diff就没有了。
查看状态
1 2 3 4 5 6 7 8 | git status # On branch master # Changed but not updated: # (use “git add …” to update what will be committed) # # modified: main.c # no changes added to commit (use “git add” and/or “git commit -a”) |
可以看到提示信息“changed but not updated”,就是说git发现你有已经修改了但还未git add的内容。 如果git提示说“Changes to be committed”,那就是表明git发现了你已经git add但还未git commit的内容。 如果git提示说“Untracked files”,那么就是你增加了新文件或者在某个子目录下增加了新文件 添加修改
1 | git add |
这句是要告诉git,我已经修改了文件,你(指git)去检查一下。当然,如果你新增加了一个文件,比如new.c,也需要在这里先执行git add new.c告诉git。
提交修改
1 | git commit -m "some comments for this update" |
查看日志
1 | git log |
总体流程就是
- git add remote 添加远程仓库
- git init 初始化项目
- git add . 添加整个项目
- git commit 提交整个项目
- 修改源文件
- git diff 发现哪些文件被修改了
- git status 查看状态
- git add 将修改过的文件通知git
- git commit 提交修改
- git log 查看日志
有一个快捷的方法git commit -a,这个命令可以直接提交所有修改,省去了你git add和git commit的工序,但是如果新建了一个目录,还是要进入那个目录git add .后再git commit,无法使用这个快捷方式。
另外,对于commit中的描述,第一行一定要是少于50字的开发概括信息,而且第二行务必是空行,第三行开始才可以开始细致描述开发信息。这是因为很多版本服务系统中的email机制都会选取log中的第一行为邮件题目。
使用gitosis来配置管理git服务器端
by Elton on 七.21, 2009, under Linux
1. 安装git
1 | emerge -av dev-util/git |
2.安装gitosis
git环境默认是可以直接使用的,但需要为每个成员开ssh权限帐号,且各个仓库之间的交叉权限管理很麻烦,所以需要使用gitosis, 它无需为每个开发人员开设ssh帐号,安全方便。
1 | emerge -av gitosis |
如果提示这个包被mask了,需要编辑/etc/portage/package.keywords文件,在里面加入
1 | dev-util/gitosis ~amd64 |
3.生成公钥
在客户端使用
1 | ssh-keygen -t rsa |
来生成ssh的key,注意你的主机名需要是全部英文字符,不能有下划线或者.之类的特殊字符,否则后面在服务端生成版本库的时候会报错。
4.上传公钥
从客户端把刚刚生成的公钥上传到服务器上。
1 | scp ~/.ssh/id_rsa.pub USER@YOUR_SERVER:/tmp |
5.在服务端生成管理库
1 | sudo -H -u git gitosis-init < /tmp/id_rsa.pub |
成功的话,你将看到类似下面的提示:
1 2 | Initialized empty Git repository in /var/spool/gitosis/repositories/gitosis-admin.git/ Reinitialized existing Git repository in /var/spool/gitosis/repositories/gitosis-admin.git/ |
设置post-update脚本权限
1 | chmod 755 /var/spool/gitosis/repositories/gitosis-admin.git/hooks/post-update |
至此,服务端配置已经完成。
6.同步配置文件
gitosis本身就是一个git库,所以管理起来非常方便。下面在客户端同步gitosis管理库
1 2 | git clone git@YOUR_SERVER:gitosis-admin.git cd gitosis-admin |
你将看到以下文件
1 2 | -rw-r--r-- 1 garry garry 104 Nov 13 05:43 gitosis.conf drwxr-xr-x 3 garry garry 102 Nov 13 05:43 keydir/ |
gitosis.conf是gitosis的配置文件,用于配置用户和权限
keydir/是所有组成员的公钥
我们可以在本地修改配置更改权限,然后push到服务端后,服务器端就立刻生效
7.创建新的repositories
打开gitosis.conf文件,你将看到
1 2 3 | [group gitosis-admin] writable = gitosis-admin members = elton@macbook |
这个是管理组的权限,members中的用户名就是刚才上传的公钥里面的用户名。
在这个文件后面加入:
1 2 3 | [group myteam] members = elton@macbook writable = free_monkey |
这里你定义了一个叫myteam的组,授予elton@macbook这个用户写“free_monkey”这个repo的权限
1 2 | git commit -a -m "Allow elton write access to free_monkey" git push |
上面的操作就更新了服务端的权限。
下面就开始创建free_monkey的repo
1 2 3 | mkdir free_monkey cd free_monkey git init |
创建 .gitignore 文件,用于忽略某些不需要进行代码管理的内容,如rails的应用可能如下:
1 2 3 4 5 | .DS_Store log/*.log tmp/**/* config/database.yml db/*.sqlite3 |
提交代码:
1 2 3 4 5 | git remote add origin git@YOUR_SERVER_HOSTNAME:free_monkey.git git add . git commit -a -m "initial import" git push origin master:refs/heads/master |
接下来,可以增加成员的公钥到系统中了
1 2 3 4 | cd gitosis-admin cp ~/alice.pub keydir/ cp ~/bob.pub keydir/ git add keydir/alice.pub keydir/bob.pub |
修改gitosis.conf
1 2 3 4 | [group myteam] - members = jdoe + members = jdoe alice bob writable = free_monkey |
提交修改:
1 2 | git commit -a -m "Granted Alice and Bob commit rights to FreeMonkey" git push |
其它成员就可以获取代码了
1 | git clone git@YOUR_SERVER:free_monkey.git |


