Git详解(二)

Git中级用法:

Ignoring files
项目里总会出现你 不想跟踪的文件。当然这些文件你不对它们进行git add操作就行了,但是这样也很麻烦, 如果使用git add .命令和git commit -a命令呢?你能告诉git去忽略一些文件,我们只需要在我们工作目录顶级创建一个.gitignore文件就可以了。就像这样:
$ vi .gitignore

# Lines starting with '#' are considered comments.
# Ignore any file named foo.txt.
foo.txt
# Ignore (generated) html files,
*.html
# except foo.html which is maintained by hand.
!foo.html
# Ignore objects and archives.
*.[oa]
# Ignore log direction and .DS_Store files
/log
.DS_Store

你 可以到[url]http://www.kernel.org/pub/software/scm/git/docs /gitignore.html[/url]看 gitignore的详细解释。你也可以把.ignore文件当到你工作目录里的任意tree目录里,然后你只需要把这个.ignore文件加到你的 git 控制下,使用git add命令。

Rebasing
假设你在远程的分支origin上创建了一个分支mywork。
$ git checkout -b mywork origin
创建一个新分支并选中它。
然后你做了一些改变:
$ vi file.txt
$ git commit
$ vi otherfile.txt
$ git commit

与 此同时,另外一些人在origin branch 上也做了一些工作,创建了两个提交。这就意味着origin和mywork会有冲突。在这一点上,你可以用pull来merge你的改变,结果是创建了一 个新的merge commit。 但是你只想在mywork分支上保留你的commit历史,而不需要任何merge,那么你可以选择使用git rebase:
$ git checkout mywork
$ git rebase origin

这个命令会把你每次从mywork的提交都会以补丁的形式暂时保存在一个叫.git/rebase的目录下,当更新到origin的最新版本的时候,就会把这个补丁给新的mywork打回去,这样,就不会有任何merge commit在历史记录里。

一旦你的‘mywork’引用指向的是新被创建的那个commit对象,那么老的commit对象会被遗弃,如果你运行垃圾回收器(git gc),它们很可能会被移除。

如果rebase的过程发现冲突,那么在你解决冲突以后,使用git add命令把它们再次更新到git index里,然后你要使用:
$ git rebase --continue

接着中断前的rebase来,但是如果你想返回到你rebase前的状态,那只能让这个过程流产了:
$ git rebase --abort


Interactive Rebasing
你可以使用互动的rebase,使用这个模式,你可以在把它们提交到某地之前重写你自己的commit对象。 它可以让你容易分离merge和re-order commit, 你也可以清除已经pull到本地的commits。

你可以在git rebase后面加参数 -i,和 --interactive来给commit应用interactive模式。$ git rebase -i origin/master

一旦你执行了git rebase  -i,你就会被扔到编辑模式,我本地的代码库已经乱了,所以偷个例子吧,呵呵:
pick fc62e55 added file_size
pick 9824bf4 fixed little thing
pick 21d80a5 added number to log
pick 76b9da6 added the apply command
pick c264051 Revert "added file_size" - not implemented correctly

# Rebase f408319..b04dc3d onto f408319
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

这是说,你有5个提交。每个提交遵循下面的格式:
(action) (partial-sha) (short commit message)

现在你可以改变那个action(默认是pick),可以改成,edit或squash,或者只是保留pick。你也可以reorder commit,移除你不想要的那行就行了。当你退出编辑模式,git就会尝试应用新的commit。


Interactive Adding
这是个好方法,你可以用它来微操你的每次git add 文件到git index。 启动这个模式的命令就是:
git add -i
然后输出:
$>git add -i
           staged     unstaged path
  1:    unchanged        +4/-0 assets/stylesheets/style.css
  2:    unchanged      +23/-11 layout/book_index_template.html
  3:    unchanged        +7/-7 layout/chapter_template.html
  4:    unchanged        +3/-3 script/pdf.rb
  5:    unchanged      +121/-0 text/14_Interactive_Rebasing/0_ Interactive_Rebasing.markdown

*** Commands ***
  1: status   2: update   3: revert   4: add untracked
  5: patch    6: diff     7: quit     8: help
What now>

看到那些命令了吧。你可以选择,如果不懂,可以输入8,然后回车,就会输出帮助:
status        - show paths with changes
update        - add working tree state to the staged set of changes
revert        - revert staged set of changes back to the HEAD version
patch         - pick hunks and update selectively
diff          - view diff between HEAD and index
add untracked - add contents of untracked files to the staged set of changes
*** Commands ***
  1: [s]tatus      2: [u]pdate      3: [r]evert      4: [a]dd untracked
  5: [p]atch      6: [d]iff      7: [q]uit      8: [h]elp
What now>
当然你不输入数字,直接输入help也是一样的效果。

这种模式下,你有多种选择。当你选择完毕以后,那么输入7或q退出,然后git commit你的改变,记住这里不要用git commit -a,否则你前面都做无用功了。

Stashing
当你在工作中发现一个不相关的但是却显而易见微不足道的bug的时候,你可能想在继续你的工作之前修复它。你可以用git stash来保存当前的工作状态,在修复完那个bug之后,再回来继续。
$ git stash "work in progress for foo feature"

这个命令会把你当前的改变保存到stash,并且会重新设置你的工作tree和匹配index到你修改bug的状态,这样在你提交修改bug代码的时候,就不会和你之前做的工作相冲突了:
... edit and test ...
$ git commit -a -m "fix:bugs"

然后,你可以回到你之前的工作状态:
$ git stash apply

很好很强大。 svn好像没这功能吧?

Stash Queue

你可以stashing了多个状态(老是修bug)

这可以看到这个stash list:
$>git stash list
stash@{0}: WIP on book: 51bea1d... fixed images
stash@{1}: WIP on master: 9705ae6... changed the browse code to the official repo
你可以使用命令来回到你想去的那个stash:
git stash apply stash@{1}
清除stash可以用命令:
git stash clear

Git Treeishes

除了吃力的写出那40位的sha乱码来引用一个commit对象或是tree对象之外,还有很多方法。在Git里这些被称为 treeish。

Partial Sha
如果你的commit sha是980e3ccdaac54a0d4de358f3fe5d718027d96aae,git可以通过下列标识来识别它:
980e3ccdaac54a0d4de358f3fe5d718027d96aae
980e3ccdaac54a0d4
980e3cc

我自己试了试前5位,ms也能识别。

Branch, Remote or Tag Name
你也可以用branch,remote,tag name代替一个sha。
如果你的master 分支是在980e3 commit上,而且你也把它push到了origin,并且它也有一个tag name叫v1.0,那么下面这些是等价的:
980e3ccdaac54a0d4de358f3fe5d718027d96aae
origin/master
refs/remotes/origin/master
master
refs/heads/master
v1.0
refs/tags/v1.0
都代表同一个commit object
$ git log master

$ git log refs/tags/v1.0
输出是一样的。

Date Spec

git log master@{yesterday}
git log master@{1 month ago}
注意这种格式的,得到的sha会是不同的。

Ordinal Spec
git log master@{5}, 同上。

Carrot Parent
这会给你一个特别commit的第n次父类。这个格式仅对merge commits有用 - commit对象有大于一个的父类。
master^2

Tilde Spec
给你第n次commit对象的外祖父类。上上级。
master~2
这会返回这个master指向的commit对象的第一个parent的第一个parent。等价于:
master^^
你也可以这么做:
master^^^^^^
master~3^~2
master~6

 Tree Pointer
master^{tree}

Blob Spec
master:/path/to/file

Range
你可能指定一个commit的范围,那么:
7b593b5..51bea1
它会包含从7b593b5开始的每次提交:
7b593b5..

Tracking Branches
一个tracking branche是指链接到远程分支的一个本地分支。当你往这个分支push和pull的时候,会自动的的push或pull到远程的那个分支。

git clone命令会自动的设置一个master分支,它是origin/master的tracking branch。
你也可以通过--track参数手动创建一个tracking branch:
git branch --track experimental origin/experimental
然后,当你运行:
$ git pull experimental
它会自动的从origin取代码,并且merge origin/experimental到你本地的experimental分支。
同样,当你push到origin,它会push你experimental分支到origin的experimental。

Finding with Git Grep
使用git grep([url]http://www.kernel.org/pub/software/scm/git/docs/git-grep.html[/url])可以很方便的查找文件。这和通常的unix命令grep功能类似。
例如,我想查看在git版本库里用到def的每个地方,我可以运行:
$ git grep def
config/boot.rb:RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
config/boot.rb:    def boot!
config/boot.rb:    def booted?
config/boot.rb:      defined? Rails::Initializer
config/boot.rb:    def pick_boot
config/boot.rb:    def vendor_rails?
config/boot.rb:    def preinitialize
config/boot.rb:    def preinitializer_path
config/boot.rb:    def run
...

如果我想看行数,我也可以加-n参数:
$ git grep -n def
config/boot.rb:4:RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
config/boot.rb:8:    def boot!
config/boot.rb:15:    def booted?
config/boot.rb:16:      defined? Rails::Initializer
config/boot.rb:19:    def pick_boot
config/boot.rb:23:    def vendor_rails?
config/boot.rb:27:    def preinitialize
config/boot.rb:31:    def preinitializer_path
config/boot.rb:37:    def run
...

如果是仅仅感兴趣它在哪个文件,我们可以用--name-only参数:
$ git grep --name-only def
config/boot.rb
config/environment.rb
config/initializers/inflections.rb
config/initializers/new_rails_defaults.rb
config/routes.rb
...

我们也可以看有多少行匹配def:
$ git grep -c def
config/boot.rb:18
config/environment.rb:9
config/initializers/inflections.rb:1
config/initializers/new_rails_defaults.rb:2
config/routes.rb:2

更多可以看git grep的文档。


Undoing in Git - Reset, Checkout and Revert

 Fixing un-committed mistakes
如果你已经混乱了你的working tree,但是还没有提交,那么可以使用这个命令来恢复到最近提交时候的状态:
$ git reset --hard HEAD
这个命令会扔掉你所有的改变,包括已经加到git index里的改变。

如果你只是想restore一个文件,那么使用checkout:
$ git checkout -- hello.rb
$ git checkout HEAD hello.rb

Fixing committed mistakes
对于已经提交的错误,有两个方法:
你可以创建一个新的commit,去undo你旧的提交做的那些事情。这是个正确的做法。

你也可以返回来修改旧的commit。一般不要这样做。

Fixing a mistake with a new commit
使用git revert命令:
$ git revert HEAD

你也可以revert更早的commit,例如:
$ git revert HEAD^

Fixing a mistake by modifying a commit

可以使用git rebase -i 修改你的commit,或用--amend参数。

Maintaining Git
Ensuring good performance
对于一个大的git仓库,可能会有一些历史信息占用了太多的空间或内存。那么可以用命令:
git gc
输出:
git gc
Counting objects: 810, done.
Compressing objects: 100% (723/723), done.
Writing objects: 100% (810/810), done.
Total 810 (delta 95), reused 0 (delta 0)
Removing duplicate objects: 100% (256/256), done.

Ensuring reliability
git fsck命令会在代码仓里执行一些检查并返回一些问题报告,最常见的警告是关于dangling对象:
git fsck
dangling blob 1b2b2a5e3f9518e2aa243337683391451b281d7c


Setting Up A Public Repository
假设你的私人repos是在~/.proj下面。我们首先要创建一个repos的新的clone,并且告诉git-daemon 它是public的:
$ git clone --bare ~/proj proj.git
$ touch proj.git/git-daemon-export-ok
这个结果是导出一个‘赤裸的’git repos。

下一步copy proj.git到你计划作为一个public repos的服务器。你可以用scp,rsync,或者其他。

Exporting a git repository via the git protocol
这是首选的方法。
可以启动git daemon服务,详细的看:[url]http://www.kernel.org/pub/software/scm/git/docs/git-daemon.html[/url]

Exporting a git repository via http
$ mv proj.git /home/you/public_html/proj.git
$ cd proj.git
$ git --bare update-server-info
$ chmod a+x hooks/post-update
最后两行代码可以参看:
[url]http://www.kernel.org/pub/software/scm/git/docs/git-update-server-info.html[/url]
[url]http://www.kernel.org/pub/software/scm/git/docs/githooks.html[/url]
这样就可以了:
$ git clone [url]http://yourserver.com/~you/proj.git[/url]

 Setting Up a Private Repository

Repo Access over SSH

最简单的方式是通过ssh来使用git。

$ git clone --bare /home/user/myrepo/.git /tmp/myrepo.git
$ scp -r /tmp/myrepo.git myserver.com:/opt/git/myrepo.git

Multiple User Access using Gitosis
如果不想为每个用户都开一个单独的帐号,你需要用一个叫gitosis的工具。
[url]http://www.urbanpuddle.com/articles/2008/07/11/installing-git-on-a-server-ubuntu-or-debian[/url]


本文出自 “{ :Alex Space => " Ruby Notes " } ” 博客,请务必保留此出处http://blackanger.blog.51cto.com/140924/123399

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值