git小技巧,gitignore只忽略当前目录下的某文件等等

#. 编写git的gitignore文件时如何只忽略当前目录下的某文件呢

在文件名前加斜线 / 即可

 

# git pull如何从remote中拉下来所有分支

git pull –all

git branch -a 查看目前所有分支,包括tracking branch

再用 git branch –track branch_name start_point 开一个本地分支,并且设好该本地分支的upstream

 

# git 10小时免输git密码

git config --global credential.helper "cache --timeout=36000"

如果需要清空存下来的密码:

git config –global –unset credential.helper

Git 的M,T,D,A,U标志是什么意思

在使用git checkout , git status,或git diff files时会出现奇怪的标志。如M,T,D,A,R,U等等。

如:

# git checkout master

M     cpp-iniparser

文件cpp-iniparser前面有个M. git的这些奇怪标志是什么意思呢。

A: 增加的文件.

C: 文件的一个新拷贝.

D: 删除的一个文件.

M: 文件的内容或者mode被修改了.

R: 文件名被修改了。

T: 文件的类型被修改了。

U: 文件没有被合并(你需要完成合并才能进行提交)

X: 未知状态。(很可能是遇到git的bug了,你可以向git提交bug report)

在git diff-files的手册man git diff-files中可以查到这些标志的说明。

这些状态标志在git的源代码的diff.h文件中被定义。

copyright ykyi.net

使用Git的submodule功能管理第三方库

用Git的Submodule功能来管理代码中使用的其它库,还是满方便的。主要用到三个命令:

Git submodule add, git submodule init, git submodule update.

git submodule init to initialize your local configuration file and git submodule update to fetch all the data from that project and check out the appropriate commit listed in your superproject.

还有两个查看相关信息的命令git submodule summary,和 git submodule status.

Git的submodule功能带来的好处和坏处都很多,网上有大量的贴子反对使用git submodule。

我觉有限制地,在以下场景用git submodule管理第三方库的代码还是很不错。

1.    你使用的第三方库更新非常慢,甚至不更新,它的接口很稳定。比如:管理vim的插件们。

2.    第三方库以比较固定的周期更新。于是,过一段时间再把上游的代码拉到submodule上来。

3.    第三方库虽然更新很快,但我过一段时间才拉取上游代码也无所谓。

如果单开一个git clone管理第三方库,与自己的项目平行,当然也是可以的。但这样有个问题是,别人git clone了你的项目,还需要再git clone一次你的项目依赖的项目,并放在适当的相对路径上。而使用git submodule *时,你的项目和你依赖的库是层级关系,有条理得多。

 

还有一种方式是把第三方库的代码合并到自己的代码中。这样做的坏处是显而易见的,如果你要合并上游代码的FIX或功能加强,都非常的麻烦。大多数人是不会去做这个同步的,于是代码会被手动复制,越来越多的细微改动分散在各个不同的项目的相同/相近代码中。一片混乱….

使用Git Submodule时忽略Submodule的改动:

如果submodule中有生成新文件。在父工程(superproject)中用git status,就总会提醒你git submodule子模块有还没被跟踪的文件。

比如:一次make会生成很多.o,.dep文件。比如用git submodule管理vim插件会生成各种临时文件。你不想让git status提醒你,这多么烦人啊。

如下,git status总提醒我cpp-iniparser子模块有未跟踪的文件:

root@vicarious:/home/kamus/projs/horoscope# git status
# On branch dev
# 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)
#   (commit or discard the untracked or modified content in submodules)
#
#    modified:   configuration.cpp
#    modified:   configuration.h
#    modified:   cpp-iniparser (untracked content)

如何让git忽略到这个提醒呢,解决方法是编辑父工程中的.gitmodules文件。加入 ignore = dirty。如下:

[submodule “cpp-iniparser”]
    path = cpp-iniparser
    url = https://github.com/zausiu/cpp-iniparser
    ignore = dirty

 

git clone的代码里面有submodule,目录是空的。怎么clone子模块submodule的代码

对于git 1.6.5以后的版本,使用clone的–recursive,如下:

git clone –recursive git://github.com/foo/bar.git

对于老旧的git,可以使用git submodule init和git submodule update

比如:

git clone git://github.com/foo/bar.git

// 此处可以要先cd到子模块的目录,较新的git则不需要cd
git submodule init
git submodule update

git submodule status显示的HASH代码前的横杠-是什么意思

表示对应的子模块submodule还没有下载到本地。

git怎么删除一个子模块submodule

step 1: 删除.gitmodules文件中子模块的对应项

step 2: 删除.git/config文件中子模块的对应项

step 3:git rm …

git submoduler的160000什么意思?

当在包含有submodule的父工程中git commit以后,会有类似create mode 160000 submoduleName 的提示,这个160000的意思是:this is a special mode in git that basically means you're recording a commit as a commit as a directory entry rather than a subdirectory or a file.

其它有用的git submodule命令:

git diff –submodule: you can see that the submodule was updated and get a list of commits that were added to it

git submodule update –remote means: git goes into your submodules and fetch(git fetch) and update(git merge origin/master) for you.

git submodule update –remote –merge or –rebase

git submodule foreach 'git stash'; git submodule foreach 'git checkout -b featureA'

使用Git Submodules需要注意的地方:GOTCHA

1.    如果你修改了submodule的代码,那必须先commit submodule的这些修改,再到父工程(superproject)中提交commit。

2.    Git 在父工程中用git update会覆盖子模块的未提交的更新。

3.    如果手动修改了父工程目录下的.gitmodules文件,那么需要用git submodule sync来更新.git/config文件中的配置。

4. When run git submodule update, If your forget the –rebase or –merge. Git will just update the submodule to whatever is on the server and reset your project to a detached HEAD state.

copyright ykyi.net

设置变量GIT_CURL_VERBOSE可以帮助调试git出错

今天操作git的时候又出错了:

error: Failed connect to github.com:8080; No route to host while accessing https://github.com/zausiu/gryphon/info/refs
fatal: HTTP request failed

 

之前用公司的http代理上git, 

#git config -l

http.proxy=http://web-proxy.oa.com:8080

 

设置变量GIT_CURL_VERBOSE可以看到详细的出错情况:

#export GIT_CURL_VERBOSE=1

# git pull
* Couldn't find host github.com in the .netrc file; using defaults
* About to connect() to proxy web-proxy.oa.com port 8080 (#0)
*   Trying 10.14.36.100…
* 0x23d67b0 is at send pipe head!
* STATE: CONNECT => WAITCONNECT handle 0x23df5f0; (connection #0) 
* No route to host
* Failed connect to github.com:8080; No route to host
* Closing connection #0
* Couldn't find host github.com in the .netrc file; using defaults
* About to connect() to proxy web-proxy.oa.com port 8080 (#0)
*   Trying 10.14.36.100…
* 0x23d67b0 is at send pipe head!
* STATE: CONNECT => WAITCONNECT handle 0x23df5f0; (connection #0) 
* No route to host
* Failed connect to github.com:8080; No route to host
* Closing connection #0
error: Failed connect to github.com:8080; No route to host while accessing https://github.com/zausiu/gryphon/info/refs
fatal: HTTP request failed

copyright ykyi.net

 

 

 

为什么我的名字没有出现在github的contributor列表中.

为什么我没有出现在github.com的contributor列表中.

我提交了commit,但为什么我没有出现在贡献者列表中呢。有三个原因:

1. 检查你的commit中的邮箱信息,这个邮箱必须和你的github.com账号关联。怎么关联邮箱账号呢。先选择Account Setting, 在左边先Emails,于是就看到可以verify邮箱地址的页面了。关联邮箱地址后还有过一段时间,贡献者列表才会更新。

2. 如果工程的贡献者名单列表超过了100个。就不会显示100个以后的贡献者了。官方HELP中说这是为了性能的考量。我觉得是码农偷懒,必竟这个需求太小了。绝大多数工程不会超过100个贡献者,于是码农不想解决这个小问题。

3. 你的commit必须被提交到工程的默认分支上。如果提交到其它的分支上,你的名字就不会被显示。

 

为什么我没有出现在github.com的contributor列表中.

我提交了commit,但为什么我没有出现在贡献者列表中呢。有三个原因:

1. 检查你的commit中的邮箱信息,这个邮箱必须和你的github.com账号关联。怎么关联邮箱账号呢。先选择Account Setting, 在左边先Emails,于是就看到可以verify邮箱地址的页面了。关联邮箱地址后还有过一段时间,贡献者列表才会更新。

2. 如果工程的贡献者名单列表超过了100个。就不会显示100个以后的贡献者了。官方HELP中说这是为了性能的考量。我觉得是码农偷懒,必竟这个需求太小了。绝大多数工程不会超过100个贡献者,于是码农不想解决这个小问题。

3. 你的commit必须被提交到工程的默认分支上。如果提交到其它的分支上,你的名字就不会被显示。

 

copyright ykyi.net

 

 

 

如何删掉github上的master分枝.

假设,代码已经被clone到了本地。第一步要做的就是创建一个新的分支,比如placeholder,然后用-D从本地删除master分支。

git branch placeholder
git checkout placeholder
git branch -D master

如果现在删除github上的master,会报错:

git push origin :master

报错结果大概是这样:

remote: error: refusing to delete the current branch: refs/heads/master
To git@github.com:matthew-brett/datarray.git
! [remote rejected] master (deletion of the current branch prohibited)
error: failed to push some refs to 'git@github.com:matthew-brett/datarray.git'

正确地做法是先checkout到新建的placeholder分支。然后把placeholder推送到github上。

git checkout placeholder # if not on placeholder already
git push origin placeholder

从github的web端入到工程的setting界面,有个地方可以更改默认的分支,用另一个分支做默认分支,而不是master。现在就可以从删掉master了

git push origin :master

另,怎么给github上一个tag更名等:

1) 删除本地的一个tag: git tag -d v0.4
2) 删除GitHub上一个tag (这会删除掉下载链接): git push origin :v0.4
3) 给当前branch打标签: git tag -a v0.5 -m "Version 0.5 Stable"
4) 把所有tag推上github(two dashes): git push --tags

copyright ykyi.net

git的排错神器pickaxe和git blame

git log -Sstring 这里的-S选项被称作pickaxe,这是一个非常好的排错工具。

比如: git log -Sinclude –pretty=oneline –abbrev-commit init/version.c

会把减少了,或者增加了include的commit全部找出来。

要注意的是,如果有一个提交增加和减少include的次数一样,这个commit不会被列出来。

/////////////

另外一个排错工作是 git blame:

git blame可以用来帮助查找引入bug的commit。git blame告诉你谁,什么时候,是哪个commit更改了某个文件。

如: git blame -L 32, init/version.c

knowledge gained from learning git.

# If you inadvertently remove a file of your working copy. Don't worry. Git are good at recovering old versions of files, such as:
$git checkout HEAD — data

 

# show what the file looks like in a certain branch.
$git show branch_name:file_name

# In newer versions of Git, git diff –ours is a synonym for git diff HEAD, because it shows the differences between "our" version and the merged version. Similarly, git diff MERGE_HEAD can be written as git diff –theirs. You can use git diff –base to see the combined set of changes since the merge base, which would otherwise be rather awkwardly written as:
git diff $(git merge-base HEAD MERGE_HEAD)

# While you are in the process of resolving a conflict, you can use some special git log options to help you figure out exactly where the changes came from and why. Try this:
$git log –merge –left-right -p
–merge shows only commits related to files that produced a conflict.
–left-right displays < if the commit was from the "left" side of the merge("our version", the one you started with), or > if the commit was from the "right" side of the merge("their" version, the one you're merging in).
-p shows the commit message and the patch associated with each commit.

If your repository were more complicated and several files had conflicts, you could also provide the exact file names you are interested in as a command line option, like this:
$git log –merge –left-right -p hello

# The -s option to git ls-files shows all the files with all stages. If you want to see only conflicted files, use the -u option instead.

# $ git checkout -m branch_name
If possible or if specifically requested with the -m option, Git attempts to carry your local change into the new working directory by performing a merge operation between your local modifications and the target branch.

# $ git reset –hard ORIG_HEAD
If you want to abort or discard the merge after it has finished(that is,after it has introduced a new merge commit), use the above command. Prior to beginning the merge operation, Git saves your original branch HEAD in the ORIG_HEAD ref for just this sort of purpose.
You should be very careful here, though. If you did not start the merge with a clean working directory and index, you could geet in trouble and lose any uncommitted changes you have in your directory.

# Just show what the file looks like in a branch.
$ git show branch_name:file_name

# The command for manipulating remotes is git remote. This operation introduces a few new settings in the .git/config file.