git 学习笔记 之 服务器上的 Git

原书中文版网址: here

为什么需要远程 git repo? 共享, 合作, 集成, 备份?
本地 repo <- pull, push -> 远程 repo
远程 repo 没有人在开发 -> no work directory -> so bare repository -> just need files in .git folder
git repo 所管理的所有东西, 都是 .git 目录下的文件 -> 它根据 git 自己定义的组织结构存在

架设 "git server" -> 通信 -> 选择协议 (file, ssh, http/https, git).

file 本地共享, 方便, 不安全, 灾难备份, 有时候许挂载;
ssh 同时支持 读, 写的网络协议, ssh 最常见, 安全, 基于用户名密码访问, 不利于共享, 和匿名访问;
git 自带的守护线程(9418), 需要 git-daemon-export-ok 文件, 没有加密&授权机制, 要么全部允许推送, 要么全部不允许;
http/https 简便, 便于分享, 需要 post-update hook, 如果需要推送 -> WebDAV, 端口常见, 效率低

"git server" 的关键点在于管理用户权限, ssh for each user? or shared account? or LDAP integratoin?

gitosis 可以帮我们管理 authorized_keys 中所有的 public key;
貌似Gitolite 更强大, 管理的细节竟然到了某 branch, refs 了.

服务器上的 git, 而不是 git server

上周看到 ddwrt 的 repo 中有 git, 就突发奇想, 是不是可以在路由器上搭一个 git server.
后来发现, 其实并没有 git server, 只有 server 上的 git.

首先, git 维护的是 .git 目录下面的所有文件和文件夹, repo 之间 push/pull 的效果是: .git 目录下面文件的相互 copy.
服务器上的 git 默认是没有监听线程的, 所以如果你 push, 其实是把文件 copy 到 server 上的某个 .git 文件夹下面. 一般我们用的还是 ssh 协议, 其实类是你 ssh 登录到 server, 然后用 vi 写 .git 文件夹下的文件.

所以最简单的 "git server" 是你在一个大家都可以访问的 server 初始化一个存放 .git 文件夹下所有文件的目录. 然后开放 ssh 协议, 凡是能够 ssh 登上这台 server 的人, 可以可以 push. pull 就是完全 copy 下来.

之所以有 git server 的惯性思维, 是因为我们经常用 github, gitlab 这样的 git web 管理 server, 是这些 web server 给了我们一个浏览我们 git 保存的历史版本的工具.

除了 github, gitlab (免费)之外, 还有一些比较方便的共享 repo 的方法 8 ways to share your git repository

另外: 服务器上的 Git - 协议

NCR 访问 google.com 而不是 google.com.hk

为了搜个英文材料, google 总是自动跳转到 google.com.hk 即使点了右下角的 使用 google.com 仍旧跳转到 hk. 登录 google 帐号, 也不可以, 使用代理也不可以.

搜了一下, 如果访问 http://www.google.com/ncr 就能访问 google.com 的服务了.
据说这个 NCR 是 No Country Redirect 的意思.

java monitor lock

每个 Java 对象都关联一个 monitor, 运行的线程可以对 monitor 进行 lock 或者 unlock. 同一时刻, 只能有一个线程获得一个对象的锁, 其它尝试获得此锁的线程都被 block 住, 直到当前线程释放此锁.

要使用 java.lang.Object 的 wait, notify 方法, 必须获得此对象的 monitor 的 lock, 所以 wait, notify, notifyAll 必须在获得此锁的 synchronized 的代码块中.

最基本的线程等待, 是使用 while(true) { //break 条件 或启动新线程/进程去做事;}, 但是这种是一直占用 CPU, 称之为 busy waiting. 如果想暂时不占 CPU 可以让线程 inactive, 等到一定条件唤醒线程. java 让线程 inactive 的方法是 wait(), wait(时间); 唤醒的方式是 notify, notifyAll,(必须是同一个对象), 或者 发出interupt 信号.

另外一个让线程暂时休眠的方法是 Thread.currentThread().sleep(时间). 让线程暂时休眠固定的时间, 倒是自动醒来, 不需要唤醒.

参考: Chapter 17. Threads and Locks

git 学习笔记<Version Control With Git>

好记性不如烂笔头, 今天理解并记住, 并不保证下次想用的时候还能理解

  1. git object store 存储4类: blob, tree, commit, tag;
  2. blob 存储的是文件的内容, 并被压缩, 算出 hash 为160bit, 40位16进制数字, 前2位作为文件夹名, 后面做文件名;
  3. git 是以内容寻址的, 只要内容一样, 生成的 blob 对象是一个;
  4. tree 相当于 linux 文件系统的 node, 存储系统某个文件夹结构. 它指向该文件夹下面的 blob 文件和 文件夹 tree;
  5. git cat-file -p [commit id | hash value] 可以看commit, tree, blob 的内容;
  6. 当某文件改变之后, 如果 commit, 那么该文件将会出现一个新的 blob 对象, 那么它上面文件夹对应的 tree 也会为了反映新的变化, 而出现一个新的 tree, 对应的, 递归向上, 直到 git 管理的顶层文件夹, 对应的 tree 都会出现新的一份. 没有改变的文件/文件夹的 hash 值没变, 那么他们对应的 blob 和 tree 都没有变, 新的 tree 还是指向它文件夹下的这些原有而没变的blob, tree 对象.
  7. 每个 commit 仅仅指向最顶层的 tree 对象, 每次有新的 commit, 最顶层的 tree 都会有新的一份. 并且每个 commit 都会指向它之前的 commit, 称之为 parent commit;
  8. 因为每个 commit 都指向最顶层的 tree, 那么顺藤摸瓜, 每个 commit 都能顺着顶层的 tree 找到当时的所有文件/文件夹的 snapshot;
  9. index/stage/cached 要么指向 HEAD 指向的 blob/tree, 要么指向 add 的 blob/tree;