分类:Git| 发布时间:2014-04-28 07:34:00
Bare代码库是没有工作目录的也不应该用来做普通的开发,可以通过git clone --bare选项来创建bare代码库
我们之前讨论的都是Development代码库,用于日常的开发,它会维护当前分支并在工作目录签出当前分支。
git clone命令通常用于根据你指定的original代码库来创建一个新的代码库。 Git不会复制original代码库的所有内容。 在普通的git clone中,original代码库的本地开发分支(refs/heads/)变成新的代码库的的远程追踪分支(refs/remotes/)。 original代码库的远程追踪分支会被忽略。 original代码库的Tag会被复制,而hooks,配置文件,reflog,stash不会被克隆。
我们可以通过以下命令创建public_html的一个新克隆
$ git clone pub_html my_website
类似的,git clone也可以用于从网站上复制一个克隆
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
默认情况下,每一个新的克隆会维持一个“链接”回它的父代码库(original代码库), 保存在remote称为origin,但是original代码库并不知道这个。
你正在工作的代码库称为本地或者当前代码库,而你用于交换文件的代码库称为远程(remote)代码库。 可以使用git remote来创建,删除,操作和查看一个远程代码库的配置。 所有这些都保存在配置文件.git/config中
除了git clone外还有以下命令和远程代码库有关
当你克隆一个代码库后,你可以在你的本地代码库保留修改而不用通知upstream。 甚至你可以创建一个test分支而不用知道upstream也用一个test分支。 在克隆时,Git会根据original代码库的每个topic分支创建一个remote tracking分支。
为了定位你的代码库和其他代码库,你定义了remote。 remote是一个保存在.git/config的命名实体。 它由两部分组成:第一部分是远程代码库的地址,第二部分是refspec, 用于定义一个ref如何从一个命名空间映射到另一个命名空间。
Git支持以下几种地址格式
/path/to/repo.git
file:///path/to/repo.git
上述两种格式有细微差别,前一种通过硬连接共享对象,而后一种直接复制对象。
git://example.com/path/to/repo.git
git://example.com/~user/path/to/repo.git
ssh:///[user@]example.com[:port]/path/to/repo.git
ssh:///[user@]example.com/path/to/repo.git
ssh:///[user@]example.com/~user2/path/to/repo.git
ssh:///[user@]example.com/~/path/to/repo.git
Git也支持scp-like格式的SSH
[user@]example.com:/path/to/repo.git
[user@]example.com:~user/path/to/repo.git
[user@]example.com:path/to/repo.git
http://example.com/path/to/repo.git
https://example.com/path/to/repo.git
rsync://example.com/path/to/repo.git
refspec的语法如下:
[+]source:destination
如果指定+表示忽略fast-forward安全检查
一个典型的refspec如下:
+refs/heads/*:refs/remotes/remote/*
假设我们要将下面的代码库作为远程代码库
$ git init
Initialized empty Git repository in /home/cjl/public/.git/
$ touch index.html
$ git add index.html
$ git commit -m"Add index.html"
[master (root-commit) c42944c] Add index.html
0 files changed
create mode 100644 index.html
$ mkdir /tmp/Depot
$ cd /tmp/Depot/
$ git clone --bare ~/public public.git
Cloning into bare repository 'public.git'...
done.
$ ls -aF public.git/
./ ../ HEAD config description hooks/ info/ objects/ packed-refs refs/
$ ls -aF ~/public/
./ ../ .git/ index.html
$ ls -aF ~/public/.git
./ COMMIT_EDITMSG config hooks/ info/ objects/
../ HEAD description index logs/ refs/
因为使用了--bare选项来克隆,因此目标代码库是bare代码库, bare代码库是没有工作目录的,public.git目录相当于publib/.git目录。
$ cd ~/public/
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
$ git remote add origin /tmp/Depot/public
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[remote "origin"]
url = /tmp/Depot/public
fetch = +refs/heads/*:refs/remotes/origin/*
现在git remote在我们的配置文件中创建了一个称为origin的remote节。 origin并没有什么特殊的含义,你可以指定其他的名称。
现在让我们来完成origin remote的设置
$ git branch -a
* master
$ git remote update
Fetching origin
From /tmp/Depot/public
* [new branch] master -> origin/master
$ git branch -a
* master
remotes/origin/master
$ git show-branch -a
* [master] Add index.html
! [origin/master] Add index.html
--
*+ [master] Add index.html
$ cat > fuzzy.txt
Fuzzy Wuzzy was a bear
Fuzzy Wuzzy had no hair
Fuzzy Wuzzy wasn't very fuzzy,
Was he?
$ git add fuzzy.txt
$ git commit -m"Add a hairy poem."
[master 752a7ff] Add a hairy poem.
1 file changed, 4 insertions(+)
create mode 100644 fuzzy.txt
$ git show-branch -a
* [master] Add a hairy poem.
! [origin/master] Add index.html
--
* [master] Add a hairy poem.
*+ [origin/master] Add index.html
现在你的代码库比/tmp/Depot/public中的代码库多了一个提交
$ git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin master
发现git提交需要先设置upstream
$ git push --set-upstream origin master
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 345 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To /tmp/Depot/public
c42944c..752a7ff master -> master
Branch master set up to track remote branch master from origin.
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[remote "origin"]
url = /tmp/Depot/public
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
git push的输出显示,Git已经将修改发送到名为origin的远程代码库中了。 除此之外Git还做了额外的操作:它也会将这些修改添加到你的代码库的origin/master分支上
$ git show-branch -a
* [master] Add a hairy poem.
! [origin/master] Add a hairy poem.
--
*+ [master] Add a hairy poem.
$ mkdir /tmp/bob
$ cd /tmp/bob/
$ git clone /tmp/Depot/public.git
Cloning into 'public'...
done.
$ ls
public
$ cd public/
$ ls
fuzzy.txt index.html
$ git branch
* master
$ git log -1
commit 752a7ff4cbe8844f0ee949932a77340cbb1e8e70
Author: Jianlong Chen <jianlong99@gmail.com>
Date: Sat Feb 8 15:54:41 2014 +0800
Add a hairy poem.
可以看到,克隆已经成功,另外由于由于Bob的代码库是从从远程代码库克隆过来的, 它已经设置好了默认的地址
$ git remote show origin
* remote origin
Fetch URL: /tmp/Depot/public.git
Push URL: /tmp/Depot/public.git
HEAD branch: master
Remote branch:
master tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
现在Bob作出了自己的修改
$ git diff
diff --git a/fuzzy.txt b/fuzzy.txt
index 4281f49..bbe4737 100644
--- a/fuzzy.txt
+++ b/fuzzy.txt
@@ -1,4 +1,4 @@
Fuzzy Wuzzy was a bear
Fuzzy Wuzzy had no hair
Fuzzy Wuzzy wasn't very fuzzy,
-Was he?
+Wuzzy?^M
$ git commit fuzzy.txt
[master 0eebdf8] Make the name pun complete!
1 file changed, 1 insertion(+), 1 deletion(-)
$ git push
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 325 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To /tmp/Depot/public.git
752a7ff..0eebdf8 master -> master
现在假设Bob休假了,而你在获取Bob的更新之前作出了以下修改
$ cd ~/public/
$ git diff
diff --git a/index.html b/index.html
index e69de29..dd4d4cc 100644
--- a/index.html
+++ b/index.html
@@ -0,0 +1,5 @@
+<html>^M
+<body>^M
+My website is alive!^M
+</body>^M
+</html>^M
$ git push
To /tmp/Depot/public
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to '/tmp/Depot/public
'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
新版本的Git要求你的代码库不能比远程代码库旧。 git pull其实是分为两步的,第一步是fetch(相当于git fetch),第二步是合并或者rebase。
可以通过使用只有source ref的refspec来创建远程分支
$ git checkout -b foo
Switched to a new branch 'foo'
$ git push origin foo
Total 0 (delta 0), reused 0 (delta 0)
To /tmp/Depot/public
* [new branch] foo -> foo
可以通过只有destination ref的refspec来删除远程分支
$ git push origin :foo
To /tmp/Depot/public
- [deleted] foo
有3种方法配置远程代码库: 一种是使用git remote,另一种是git config,最后一种是直接编辑.git/config文件。
$ git remote fasfdfa
error: Unknown subcommand: fasfdfa
usage: git remote [-v | --verbose]
or: git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mir
ror=<fetch|push>] <name> <url>
or: git remote rename <old> <new>
or: git remote remove <name>
or: git remote set-head <name> (-a | -d | <branch>)
or: git remote [-v | --verbose] show [-n] <name>
or: git remote prune [-n | --dry-run] <name>
or: git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)..
.]
or: git remote set-branches [--add] <name> <branch>...
or: git remote set-url [--push] <name> <newurl> [<oldurl>]
or: git remote set-url --add <name> <newurl>
or: git remote set-url --delete <name> <url>
-v, --verbose be verbose; must be placed before a subcommand
$ git config remote.publish.url 'ssh://git.example.org/pub/repo.git'
$ git config remote.publish.push '+refs/heads/*:refs/heads/*'
这会创建一个远程名称为publish的push refspec