【转】git 学习笔记( 随时更新中…… 最后更新日期201304281518)--不错

时间:2024-12-11 09:07:08

原文网址:http://blog.****.net/yasin_lee/article/details/5975070

GIT 是版本管理的未来!

 

推荐几个GIT教程网站

http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn/index.html 

http://progit.org/book/zh/  

http://www.linuxsir.org/main/doc/git/gittutorcn.htm

http://www.linuxgem.org/user_files/linuxgem/Image/git-tutor.pdf

http://blog.enjoyrails.com/2008/12/28/git%E8%AF%A6%E8%A7%A3%EF%BC%88%E4%B8%80%EF%BC%89/

http://gitbook.liuhui998.com/

The most commonly used git commands are:

add        Add file contents to the index 向仓库中添加一个新文件(让git跟踪到这个文件)
bisect     Find by binary search the change that introduced a bug
branch     List, create, or delete branches 列出本仓库的分支,或者创建一个分支,或者删除一个分支
checkout   Checkout a branch or paths to the working tree 改变当前工作树所在分支,就是改变分支,记得改变分支前要把所有的更新提交到本地
clone      Clone a repository into a new directory 克隆一个仓库
commit提交  Record changes to the repository向本地仓库提交记录改变信息(增量信息)这是向本地提交的最后一步,写一些注释
diff       Show changes between commits, commit and working tree, etc 检视某两次提交之间的基于文件的代码变化
fetch取到   Download objects and refs from another repository从另一个仓库下载内容 从远程取回最新的代码提交,但是不更新到本地(可以理解为只更新了增量数据库),只有pull后你才能看到更新
grep       Print lines matching a pattern 查找内容并打印出相匹配的行
init       Create an empty git repository or reinitialize an existing one  如果你要把一个目录初始化为git仓库,那就是这个命令啦
log        Show commit logs 列出代码提交的历史记录
merge归并   Join two or more development histories together 版本合并
mv         Move or rename a file, a directory, or a symlink
pull       Fetch from and merge with another repository or a local branch  更新当前分支到最新
push       Update remote refs along with associated objects 把当前分支的所有提交推送到远程服务器的对应分支!!!
rebase     Forward-port local commits to the updated upstream head  更新当前分支到最新,并把当前分支中未被推送的提交记录移至最顶端
reset      Reset current HEAD to the specified state 将当前分支回退到先前的某个历史
rm         Remove files from the working tree and from the index
show       Show various types of objects
status     Show the working tree status 查看当前的修改状态
tag        Create, list, delete or verify a tag object signed with GPG  打标签

//----------------------------------------------------------------------------------------------------------------------

git init 初始化一个工作树(工作树就是被git管理的那个目录,就是.git所在的父目录,将一个普通当目录初始化后会生成一个.git,从此这个包含.git的目录就被叫做所谓的仓库)

//clone命令示例
mkdir my-repository
cd my-repository
git clone git@192.168.0.80:fsl_android_r6/kernel/imx.git
完成后我们会看到本地会有相关的目录(仓库)产生。
接下来cd到仓库,执行以下命令查看远程分支信息
git branch -r

remotes/origin/build_test  //假设这就是我们看到的远程分支,

选定一个远程分支作为跟踪对象,用以下命令创建一个本地分支。
git checkout --track origin/build_test -b build_test_my_local
含义:在本地建立一个名为build_test_my_local的分支,该分支跟踪自远程的build_test分支,也就是说将来我们更新本地分支的时候就是基于该远程分支!
此时代码还没有拉下来,接着执行如下命令更新本地分支后,我们就能在仓库中看到最新的代码了!
git pull

接下来可以修改文件了,改动一个文件内容,然后执行以下命令,你会看到git已经发现仓库中有东西被改动了
cpp@cpp:~/mywork/i850/r7_old/kernel_imx$ git status
# On branch p3_r7_20100322
# Your branch is ahead of 'origin/p3_r7_20100322' by 6 commits.
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified:   drivers/video/mxc/mxcfb_elite_svga.c
#
no changes added to commit (use "git add" and/or "git commit -a")
cpp@cpp:~/mywork/i850/r7_old/kernel_imx$ 
恩,git已经发现drivers/video/mxc/mxcfb_elite_svga.c这个文件被修改了,被改成什么样子了呢?用以下命令看看吧。
git diff drivers/video/mxc/mxcfb_elite_svga.c   //该命令会列出文件的改动差异。。。
好了,这些改动是我需要的,我现在想把这个改动push到服务器上。。。那先需要在本地做一次提交,一共两步:
第一步,
git add drivers/video/mxc/mxcfb_elite_svga.c
第二步。
git commit -m "这里写一些简明扼要的注释"
好了现在你可以用
git log
看看你当前分支的历史记录。没有问题的话你就可以向服务器推送你的代码了。这要很谨慎!因为你的推送是用你的本地仓库覆盖服务器的对应仓库!所以你要注意,如果别人在你之前已经更新了远程仓库,那你的推送就是有问题的,当然git会想办法阻止你的,最好的办法就是在push前要确保自己的本地仓库是最新的!怎么办呢?一个良好的习惯就是在每天早上开始工作之前更新本地的代码,这样可以降低和别人的提交发生冲突当概率。其次在每次提交代码前都再次更新本地代码。命令如下
git pull --rebase //这里加上rebase参数的目的是保证在将本地代码更新到最新的同时将本地的提交移至提交历史的最顶端!如果这一步是成功的,那么接下来你就可以向远程推送你的更新了,很简单的命令如下:
git push  //之所以可以这么简单是因为我们在建立当前分支的时候是很确定的跟踪了远程的一个对应分支。那么这次推送就是用本地分支替换远程的对应分支。当然了,我们也可以把本地的这个分支推送到远程的另外一个分支,那命令就要复杂一些啦,如下
git push origin localBranch:originBranch  //这个命令更要慎用。。。。因为你一不小心就会把远程分支删除。。。。  删除啊!!!!! 删除了就木有啦!!!远程服务器的啊!!!!
好了基本上一次完整的git操作就这样完成了

//----------------------------------------------------------------------------------------------------------------------
某年某月某日的一次练习记录:
git clone /home/cpp/test abc
git clone /home/cpp/test/.git abc 
这两个命令得到的结果是一样的,所以工作树和仓库可以不必分的很仔细……

test是一个被git管理的目录(工作树),现在把这个工作树clone到当前目录下并以abc作为新工作树的名字,你会发现abc目录下也会有一个.git仓库而且abc下的内容和test下的内容完全一样,所以你大可不必把工作树和仓库分的那么细, 因为你很清楚用 cp /home/cpp/test  abc 你也可以得到相同的内容!也许你会发现这两种方式根本没有什么差异!(唯一不同的地方是COPY过来的abc会不知道自己的姓什么,这会导致你在需要和远程同步的时候,本地的git会找不着北,当然git会告诉你这个问题,你需要帮助它找到正确的同步位置即可…… 所以我们应该用clone方法,而不是简单的copy命令)这也从另一方面说明.git仓库中的索引玩的的相对路径而不是绝对路径,那么也意味着git的触手永远伸不到工作树的外边…… 即git只能管理工作树中的内容!

git status 查看当前本地工作树状态

git add 123.c  当工作树中的内容发生变化了(删除文件和目录,添加文件和目录,修改文件内容)这时你如果想让git知道你作的修改的话,你可以用这个命令告诉它:“我把123.c的内容修改了!”。git不管理空目录,所以不要 "git add newdir" 当然,如果你新建立了一个目录并向其中放置了至少一个文件的话,你可以告诉git去管理它,只要这么说 "git add newdir" ,这是对的!

git add . 如果你做了大量的改动,你都记不得到底改了多少东西,那么这个命令比较管用了!他会让git知道所有的变化!

git commit -m "本次提交的简略说明(版本更新信息)……"

当你用add让git知道了你的改动之后,你可能想让你的改动生效,这时候你需要用这个命令去提交你的改动,每次提交意味着一个新的版本产生……
//----------------------------------------------------------------------------------------------------------------------

git branch 列出本地分支信息
git branch -a 列出所有的分支,包括本地的和远程的
git branch -r 列出远程分支信息
git branch newbranch 在本地创建一个名称为newbranch的新分支
git branch -d newbranch 删除一个分支
git branch -D newbranch 强制删除一个分支

更改一个已经存在的本地分支的名字:

修改当前所在分支的名字: git branch -m  [newname]

修改其他本地分支的名字:

git branch (-m | -M) [<oldbranch>] <newbranch> 

//看看这个牛B的checkout吧
git checkout   //在还未提交前,检查你做了那些修改
git checkout . //把你未在本地提交的修改都删掉,很惊愕!加不加那个小点点 。。。含义竟然天壤之别!
git checkout anotherbranch 切换到一个已经存在的分支,前提是你的修改都已经提交!
git checkout oldbranch -b newbranch 基于oldbranch创建一个newbranch并且自动切换到newbranch
git checkout origin/nb1_1_2 -b nb1_1_2_local  基于本地的远程分支origin/nb1_1_2 创建一个本地分支nb1_1_2_local并立刻切换到该本地分支
//很明显,你可以建立一个跟踪到本地远程分支的本地分支,你也可以建立一个跟踪到本地某个分支的本地分支 。什么叫本地的远程分支?。。。没错,这个不好解释,自己体会吧,只可意会。。
git checkout --track r6_20091202 -b r6_20091202_patch
基于本地分支r6_20091202创建本地分支r6_20091202_patch
git checkout -b newbranch 基于当前的代码状态(也就是当前commit状态)建一个本地分支名字叫做newbranch,该分支不会跟踪任何分支,这意味着你不能在该分支直接使用git pull

其实,打开文件.git/config你会发现类似如下的内容:
注释是我的理解
           ……
           ……
[branch "suspend_20100517"]     //本地分支名称
remote = origin
merge = refs/heads/suspend_20100517 //所跟踪的远程分支的名字,上面这两行暂时理解不了,但是从直观上可以把这两行作为一个整体一起理解成   “合并(跟踪)到远程的origin下的suspend_20100517分支”

[branch "p3_r7_20100322_for_ts"]
remote = origin
merge = refs/heads/p3_r7_20100322

[branch "wwww"]
remote = origin
merge = refs/heads/i850_WCDMA
           ……
           ……
如果你采用上述git checkout -b newbranch 的方式去创建一个分支,那么你不会在.git/config中看到上述的关于分支的  remote 、 merge 信息。基于这个原因,你就不能用git pull

cat .git/config 查看配置文件
git log 列出提交的历史记录
git log --stat --summary 列出提交的历史记录(并显示摘要)
git show  a1cc2c7d 显示版本号为a1cc2c7d的版本更新细节
git tag v0.1 a1cc2c7d 给版本号a1cc2c7d起个别名v0.1 这样好记了   这样就可以 git show v0.1  了

git reset a1cc2c7d 将当前状态回滚到版本a1cc2c7d,可将当前版本定位到之前提交的任何版本 这里还有两个参数,--soft 或者 --hard
git reset --soft  a1cc2c7d 回滚并且保留修改内容 
git reset --hard  a1cc2c7d 回滚并且删除修改历史内容

git pull [remotepath] 从远程库取得更新版本,并合并到本地库。(注意可能会发生冲突)
git push 将本地版本推送到远端

git merge newbranch 把newbranch合并到当前分支.

//----------------------------------------------------------------------------------------------------------------------
某年某月某日的一次练习记录:
git rm 5.c    //删除一个文件
现在要恢复:
git reset HEAD 5.c
git checkout 5.c
完成           HEAD似乎表示当前分支的当前版本……

git reset --hard HEAD^     恢复到上一个提交

git reset --hard e0dea1a7eaca4b9325e36fdbdf0909d02a067d43    恢复到某一个提交

//======================================================================================================================
提交步骤:
git fetch
git rebase eg. git rebase origin/r6_20091207
git push origin localBranch:originBranch eg. git push origin r6_20091207:r6_20091207   (冒号两边不能有空格)
删除远程分支:提交一个空的本地分支上去就会删掉远程分支 eg. git push origin :r6_20091207
//======================================================================================================================
How to IGNORE some file ?
1.  仓库的.gitignore
2. .git/info/exclude,在这个文件中添加你本地的不需要被管理的文件,exclude  本身不被git管理
一般情况下不要使用第一种方法,因为.gitignore 本身是被git管理的,所以.gitignore 是大家共用的。不要随便修改!
//======================================================================================================================
泉哥的一次关于cherry-pick的操作
git branch
git log
git push origin :r6_20091207
git push origin r6_20091207:r6_20091207
git merge r6_20091202
git status
git reset --hard 
git log r6_20091202
git checkout r6_20091202
git pull --rebase //拉下来,把你的改动放到最上边。。。。。 
git log
git checkout r6_20091207
git log
git status
git cherry-pick 77df80f6e1dd071317744c0aca016fbcfcf3a1e4
git cherry-pick 07f5c33a23fd97eed891852e94704c1bee32c3bc
git cherry-pick 239b4f9646a18d1f486ac6ce36f19fabfa456b37
git cherry-pick 7f5af9cca7e23a7f0521980cc06cb0c13de8022b
git log
git push origin r6_20091207:r6_20091207
cherry-pick 的功能是从另为一个分支中提取一个提交记录到当前分支,这个功能在版本合并中非常有意义!!!!!
//======================================================================================================================
merge and push TAG
git checkout stable 切换到本地的stable分支
git merge 20091210 合并本地的20091210分支到当前(stable)分支
git tag tag_i850_20091210 jaeuf765hg4r7f8r3g2iyr7r32iurt39782ryy29yr4io32y 应该在当前的分支顶端建立tag标记
git push --tags origin stable:stable
//======================================================================================================================
关于打patch:
git apply    XXX.patch   (不建议使用这种方式,因为这种方式的patch会以你的名义被commit,这是不应该的,除非这是你的patch,如果是别人的patch,则应该用下边的方法!)
或者,一次打多个相关的patch:
首先在patch所在的目录下建立一个名字为series的文件,名字就是这样!这是必要的。其内容为该目录下所有patch的名字列表。 可以这样建立: ls *.patch > series
然后cd到你要添加patch的那个仓库,用以下命令完成
git quiltimport --patch ~/mywork/patch/patches_for_prowave_091204_liangquan/kernel_imx/   (这是你的patch和series所在的目录)
//================================================================
How to MAKE patch file:
从以下hash开始到HEAD的所有commit生成一个patch组。
git format-patch 7f5af9cca7e23a7f0521980cc06cb0c13de8022b   >  PATH/series
或者你也可以这么写
git format-patch HEAD^^^  > PATH/series
这条命令的执行将会产生两部分内容:
一个是位于你指定的PATH路径下的series文件(这个文件的内容就是生成的所有patch的文件名列表)
另一个时位于当前仓库的一组patch(每个commit对应一个patch文件,且文件的的名字就是commit注释)
//============================================================================================================
about repo
repo:
1.  
$ cd ~
$ mkdir bin
$ chmom a+x bin
add 'bin' to PATH
2.
$ curl http://android.git.kernel.org/repo >~/bin/repo
$ chmod a+x ~/bin/repo
$ mkdir fsl_myandroid
$ cd fsl_myandroid
$ repo init -u git@192.168.0.80:r6_20091201/manifests.git     //这里需要注意一下,如果每个仓库都有master分支,我们就可以在这里不用加-b参数,但是如果你不能确定这个问题的话(有些人总会没有道理的删掉master分支。。。)你最好还加上-b参数,用以指定一个确定的分支用以同步(下载代码),否则,接下来同步会因为某个仓库没有master分支而无法同步。所以,需要指定一个在每个仓库中都有的一个相同的分支名,命令如下:

$ repo init -u git@192.168.0.80:r6_20091201/manifests.git   -b   the-same-branch-name-included-in-each-repository

其实我没有想明白为什么有人总喜欢让仓库里没有master分支。。。也许这样有快感吧。

$ repo sync  //到这里,你已经将远程的repo库下载到来了本地,接下来就是去相关的git目录下建立本地分支,然后pull
如果你真的想给本地的所有git库建立一个统一的分支(前提是远程也有统一的库名字)那么你可以按照如下操作!
repo forall -c git checkout --track origin/r6_20091207 -b r6_20091207
//======================================================================================================================__
某年某月某日,你的本地库和远程库是一致的,我们假设此时本地和远程的修改参考点(历史点)为A,也就是此时本地和远程有一个共同的历史参考点。现在,你开始工作了,当你在本地的工作完成并且已经提交到本地,而在你工作的这个过程中远程库被更新了,这一切你完全不知道,如果现在你打算把你的工作提交到远程库,
第一步,你会先git pull.你会发现你的工作和远程库的更新会有一个merge动作。大部分时候你不希望是这样的结果,其实此时你应该采用git pull --rebase 而不是git pull .之所以会出现merge动作是因为你本地相对于A点的修改提交和远程相对于A点的的修改提交不一致导致的。因此,你的pull动作会把从A点的两个分叉合并到一起,merge便发生了。而加上rebase参数后,会先把你的本地库更新到和远程库一致,然后把你的提交放到最顶端。。。
//======================================================================================================================__
git stash        参考:http://www.kernel.org/pub/software/scm/git/docs/git-stash.html
g如果你想保存当前未提交的改动,一般情况下你可能是想把远程的更新拉下来,而又不想把你本地的修改取消掉,那么你可以用stash !
git stash : 暂存你的未提交的修改,并将当前分支置于HEAD,也就是你看起来就好像把自己的修改全部清除了,剩下了一个干净的分支
git stash list: 列出你的。。。。。不是很懂
git stash show: 显示被你修改的文件
git stash apply: 把你曾经stash的修改复原。
其实你也只需要第一个和最后一个而已!!!

Use git stash when you want to record the current state of the working directory and the index, but want to go back to a clean working directory. The command saves your local modifications away and reverts the working directory to match the HEAD commit.

The modifications stashed away by this command can be listed with git stash list, inspected with git stash show, and restored (potentially on top of a different commit) with git stash apply. Calling git stash without any arguments is equivalent to git stash save. A stash is by default listed as "WIP on branchname …", but you can give a more descriptive message on the command line when you create one.

The latest stash you created is stored in refs/stash; older stashes are found in the reflog of this reference and can be named using the usual reflog syntax (e.g. stash@{0} is the most recently created stash, stash@{1} is the one before it, stash@{2.hours.ago} is also possible).
//======================================================================================================================__
Yasin Li update 201107111430

git diff 原来还可以这么来用!(列出某两个commit之间单个文件的差异)
git diff HEAD^   xxx/xxx/xxx.x
git diff  4843243757784218784   68746784272787187845  xxx/xxx/xxx.x

今天又学会来git diff 的另一个妙用!(只列出某两次commit之间被修改的文件路径而不列出具体内容差异)
git diff --name-only  4843243757784218785   687467842727871878
git diff --name-only HEAD^^

//----------------------------------------------------------------------------------------------------------------------------------

revert :用来提交一个新的记录用以抵消先前的一个记录,就像打了一个逆反的patch

git revert   247826513245839275892    //命令会产生一个新的提交记录,将对应hash的那次提交抵消掉

//------------------------------------------------------------------------------------------------------------

git add 不能添加一个空目录被git管理,如要添加一个目录,这个目录中至少要有一个文件才可以

//--------------------------

在一个git仓库中,每一次提交的哈希码都是唯一的,每一次提交的哈希码都是被永久保存的!所以无论你在哪个分支,无论你站在哪一次提交的顶端,只要你拥有某一个哈希码!你都可以用 git reset --hard 23848589241203845792386 跳到这个哈希码对应的历史状态,这也归因于,git的历史是线性的,是递增的!哈希码是一次历史事件,它如果发生,就不可磨灭!也就是说,如果你commit了,那你就造就了历史,谁也不能否认这次事件,谁都会知道这次历史事件!哈希码是那一刻的快照,只要你拥有哈希码,肯定的说,你可以回到那一刻,所以,你可以将一些历史重大事件的哈希码打印到纸上!

哈哈。再补充一下,git reset 后跟一个hash不仅能让你回到某个历史,也能让你返回到当前,你只要有当前的那个hash就可以了!

 

//==================================================================================================================

@201109011830

补充:


今天又学会了一个重要的东西:
历史上你曾经有多次提交都涉及到了某一个文件,那么怎么看到针对单独一个文件的修改历史呢?
很简单:git log the-path-of-the-file-you-want
现在你可以看到针对这个文件的多次修改的每一次的hash。如果你现在想看看其中一次的修改记录怎么办呢?比如这个文件在历史上有两次修改记录,你看到了两个hash,现在你想看看其中一个hash对应的修改,假如这次修改的hash为: 1234567890abcdefd 。你可以这么来看这次的修改记录:
git     log   1234567890abcdefd    1234567890abcdefd^     the-path-of-the-file-you-want
OK

顺便提一下,刚才一个和一个哥们交流标签tag的一些东西,我们可以通过git reset --hard xxxxxx-tag 让代码回退到某一个标签标记的历史状态,然后那哥们说能不能查看当前处于那一个tag ?这句话把我蒙住了。。。我就开始找有没有这样的参数呢。。。最后无功而返。。。
其实tag只是历史上某一个hash的一个别名而已。根本就没有什么当前处于某一个tag的说法。tag又不是branch 。。。。呵呵

 

git commit --amend  这个可以修改最顶端的那个commit提交的注释信息。

 

———————————————————————————————————————————————————————

201201191041:

今天添加一个如何让本地仓库同时跟踪到多个远程仓库的操作,转自http://progit.org/book/zh/ch2-5.html

远程仓库的使用

要参与任何一个 Git 项目的协作,必须要了解该如何管理远程仓库。远程仓库是指托管在网络上的项目仓库,可能会有好多个,其中有些你只能读,另外有些可以写。同他人协作开发某个项目时,需要管理这些远程仓库,以便推送或拉取数据,分享各自的工作进展。管理远程仓库的工作,包括添加远程库,移除废弃的远程库,管理各式远程库分支,定义是否跟踪这些分支,等等。本节我们将详细讨论远程库的管理和使用。

查看当前的远程库

要查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简短名字。在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库:

$ git clone git://github.com/schacon/ticgit.git
Initialized empty Git repository in /private/tmp/ticgit/.git/
remote: Counting objects: 595, done.
remote: Compressing objects: 100% (269/269), done.
remote: Total 595 (delta 255), reused 589 (delta 253)
Receiving objects: 100% (595/595), 73.31 KiB | 1 KiB/s, done.
Resolving deltas: 100% (255/255), done.
$ cd ticgit
$ git remote
origin
也可以加上 -v 选项(译注:此为 --verbose 的简写,取首字母),显示对应的克隆地址:

$ git remote -v
origin git://github.com/schacon/ticgit.git
如果有多个远程仓库,此命令将全部列出。比如在我的 Grit 项目中,可以看到:

$ cd grit
$ git remote -v
bakkdoor  git://github.com/bakkdoor/grit.git
cho45     git://github.com/cho45/grit.git
defunkt   git://github.com/defunkt/grit.git
koke      git://github.com/koke/grit.git
origin    git@github.com:mojombo/grit.git
这样一来,我就可以非常轻松地从这些用户的仓库中,拉取他们的提交到本地。请注意,上面列出的地址只有 origin 用的是 SSH URL 链接,所以也只有这个仓库我能推送数据上去(我们会在第四章解释原因)。

添加远程仓库

要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,运行 git remote add [shortname] [url]:

$ git remote
origin
$ git remote add pb git://github.com/paulboone/ticgit.git
$ git remote -v
origin git://github.com/schacon/ticgit.git
pb git://github.com/paulboone/ticgit.git
现在可以用字串 pb 指代对应的仓库地址了。比如说,要抓取所有 Paul 有的,但本地仓库没有的信息,可以运行 git fetch pb:

$ git fetch pb
remote: Counting objects: 58, done.
remote: Compressing objects: 100% (41/41), done.
remote: Total 44 (delta 24), reused 1 (delta 0)
Unpacking objects: 100% (44/44), done.
From git://github.com/paulboone/ticgit
 * [new branch]      master     -> pb/master
 * [new branch]      ticgit     -> pb/ticgit
现在,Paul 的主干分支(master)已经完全可以在本地访问了,对应的名字是 pb/master,你可以将它合并到自己的某个分支,或者切换到这个分支,看看有些什么有趣的更新。

从远程仓库抓取数据

正如之前所看到的,可以用下面的命令从远程仓库抓取数据到本地:

$ git fetch [remote-name]
此命令会到远程仓库中拉取所有你本地仓库中还没有的数据。运行完成后,你就可以在本地访问该远程仓库中的所有分支,将其中某个分支合并到本地,或者只是取出某个分支,一探究竟。(我们会在第三章详细讨论关于分支的概念和操作。)

如果是克隆了一个仓库,此命令会自动将远程仓库归于 origin 名下。所以,git fetch origin 会抓取从你上次克隆以来别人上传到此远程仓库中的所有更新(或是上次 fetch 以来别人提交的更新)。有一点很重要,需要记住,fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。

如果设置了某个分支用于跟踪某个远端仓库的分支(参见下节及第三章的内容),可以使用 git pull 命令自动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分支。在日常工作中我们经常这么用,既快且好。实际上,默认情况下 git clone 命令本质上就是自动创建了本地的 master 分支用于跟踪远程仓库中的 master 分支(假设远程仓库确实有 master 分支)。所以一般我们运行 git pull,目的都是要从原始克隆的远端仓库中抓取数据后,合并到工作目录中的当前分支。

推送数据到远程仓库

项目进行到一个阶段,要同别人分享目前的成果,可以将本地仓库中的数据推送到远程仓库。实现这个任务的命令很简单: git push [remote-name] [branch-name]。如果要把本地的 master 分支推送到 origin 服务器上(再次说明下,克隆操作会自动使用默认的 master 和 origin 名字),可以运行下面的命令:

$ git push origin master
只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,合并到自己的项目中,然后才可以再次推送。有关推送数据到远程仓库的详细内容见第三章。

查看远程仓库信息

我们可以通过命令 git remote show [remote-name] 查看某个远程仓库的详细信息,比如要看所克隆的 origin 仓库,可以运行:

$ git remote show origin
* remote origin
  URL: git://github.com/schacon/ticgit.git
  Remote branch merged with 'git pull' while on branch master
    master
  Tracked remote branches
    master
    ticgit
除了对应的克隆地址外,它还给出了许多额外的信息。它友善地告诉你如果是在 master 分支,就可以用 git pull 命令抓取数据合并到本地。另外还列出了所有处于跟踪状态中的远端分支。

上面的例子非常简单,而随着使用 Git 的深入,git remote show 给出的信息可能会像这样:

$ git remote show origin
* remote origin
  URL: git@github.com:defunkt/github.git
  Remote branch merged with 'git pull' while on branch issues
    issues
  Remote branch merged with 'git pull' while on branch master
    master
  New remote branches (next fetch will store in remotes/origin)
    caching
  Stale tracking branches (use 'git remote prune')
    libwalker
    walker2
  Tracked remote branches
    acl
    apiv2
    dashboard2
    issues
    master
    postgres
  Local branch pushed with 'git push'
    master:master
它告诉我们,运行 git push 时缺省推送的分支是什么(译注:最后两行)。它还显示了有哪些远端分支还没有同步到本地(译注:第六行的 caching 分支),哪些已同步到本地的远端分支在远端服务器上已被删除(译注:Stale tracking branches 下面的两个分支),以及运行 git pull 时将自动合并哪些分支(译注:前四行中列出的 issues 和 master 分支)。

远程仓库的删除和重命名

在新版 Git 中可以用 git remote rename 命令修改某个远程仓库在本地的简短名称,比如想把 pb 改成 paul,可以这么运行:

$ git remote rename pb paul
$ git remote
origin
paul
注意,对远程仓库的重命名,也会使对应的分支名称发生变化,原来的 pb/master 分支现在成了 paul/master。

碰到远端仓库服务器迁移,或者原来的克隆镜像不再使用,又或者某个参与者不再贡献代码,那么需要移除对应的远端仓库,可以运行 git remote rm 命令:

$ git remote rm paul
$ git remote
origin

———————————————————————————————————————————————————————

201201191041:

今天添加一个如何让本地仓库同时跟踪到多个远程仓库的操作,转自http://progit.org/book/zh/ch2-5.html

———————————————————————————————————————————————————————

201204261531:

git 从来不会让你的hash code 丢掉,即便是你用了git reset --hard 45487238479.

任何影响hash的操作均被记录在案,所以,只要你曾经commit过,那么历史总是无法磨灭的。

.git/logs/refs/heads/branch-name记录了任何可能影响hash的操作,从中你会发现,有些诸如git reset --hard 3488787676 这样的回退操作,其实也被git悄悄作为一个新的commit提交。

基于此种隐性操作,我们变不会丢掉任何被commit的东西,所以你大可放心的去玩转git,而不必顾及任何。只要适时的进行commit即可。如果你不commit,git也对你无能为力了。如果死,你就会真的很惨。。。。。。

end

———————————————————————————————————————————————————————

201304281518
这个reset还真牛逼。
将单个文件恢复到某次commit之前的状态:
git reset 52f851fd5d5827ae478622e43ef422d4ec5ab740^ include/linux/idr.h
Unstaged changes after reset:
M include/linux/idr.h
apuser@YaochuanLiubt:~/mywork/4.1/kernel$ git status
# On branch sprdroid4.1_3.4-0426
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   include/linux/idr.h
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified:   include/linux/idr.h
#
以上将include/linux/idr.h恢复到了commit:52f851fd5d5827ae478622e43ef422d4ec5ab740之前的状态。执行上述操作后。该文件已经被回复,并被stage,因此我们看到了modified内容。modified内容其实就是52f851fd5d5827ae478622e43ef422d4ec5ab740(包括)之后对该文件的修改。只要把这个checkout了就好了。
-----------------------------------------------------------------------------------------------
201309231055
我的配置
cat ~/.gitconfig 

[user]
email = zhangsan@ak47.com
name = Zhang San
[color]
ui = auto
[commit]
template = /home/apuser/.gitmessage
[core]
editor = vim

quotepath = false                            //加上这个能显示中文文件名!!!

-----------------------------------------------------------------------------------------------
20140619

在执行commit或revert等操作时,提示“bad index file sha1 signature fatal: index file corrupt”错误,导致操作失败。这是由于git的index文件出错。需要删除.git/index文件,然后在仓库目录下运行git reset,重新生成index文件。