git使用技巧分享
git使用技巧分享
基础环境优化
- 安装git,mac下是自带的且需要安装xcode ,windows下和linux下面需要安装。安装完成后基本上就可以使用git shell了
-
git config的配置:
- Git 提供了一个叫做 git config 的工具(译注:实际是 git-config 命令,只不过可以通过 git 加一个名字来呼叫此命令。),专门用来配置或读取相应的工作环境变量。而正是由这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。
- 一般来说git config会根据操作系统的不同,会存在不同的位置下面。比如/etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。~/.gitconfig,用户指定配置文件,一般我们使用git config来设置的信息都会保存在此文件中。在 Windows 系统上,Git 会找寻用户主目录下的 .gitconfig 文件。主目录即 $HOME 变量指定的目录,一般都是
C:\Documents and Settings\$USER
。此外,Git 还会尝试找寻/etc/gitconfig
文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位。 -
设置自己的信息
$ git config --global user.name "Shane Zhang" $ git config --global user.email zhangyuqing@5288z.com $ git config --global core.editor vim 这样设置的配置信息保存在~/.gitconfig,如果想在某个文件夹下单独配置只需要去掉--global即可 $ git config --list 查看刚刚配置的一些信息
-
git alias配置
git config --global alias.cm commit // git commit git config --global alias.co checkout // git checkout git config --global alias.ac '!git add -A && git commit' // git add . -A git commit git config --global alias.st 'status -sb' // git status -sb git config --global alias.tags 'tag -l' // git tag -l git config --global alias.branches 'branch -a' // git branch -a git config --global alias.remotes 'remote -v' // git remote -v git git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)%Creset' --abbrev-commit --" // git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)%Creset' --abbrev-commit --
-
让你的shell支持git基本显示,支持git语法高亮等一系列的便捷措施:
- 强烈推荐oh-my-zsh,安装步骤参见官方文档 使用zsh的九个理由
- 切换默认shell为zsh.
chsh -s /bin/zsh
- 如果你不想使用zsh。可以通过下方代码来优化bash
function find_git_branch { local dir=. head until [ "$dir" -ef / ]; do if [ -f "$dir/.git/HEAD" ]; then head=$(< "$dir/.git/HEAD") if [[ $head == ref:\ refs/heads/* ]]; then git_branch=" ${head#*/*/}" elif [[ $head != '' ]]; then git_branch=' (detached)' else git_branch=' (unknown)' fi return fi dir="../$dir" done git_branch='' } PROMPT_COMMAND="find_git_branch; $PROMPT_COMMAND" green=$'\e[1;32m' magenta=$'\e[1;35m' normal_colours=$'\e[m' PS1="\[$green\]\u@\h:\w\[$magenta\]\$git_branch\[$green\]\\$\[$normal_colours\] "
添加完后,需要执行source命令,新打开的终端里,这个函数就会生效了:
$ vim ~/.profile $ source ~/.profile
git常用的使用技巧
- 我们使用
git init
来创建一个空白的仓库,创建完成后会在目录下生成一个.git的隐藏文件夹。这一点比较好,相对于svn的每个目录下都创建一个.svn的文件夹要好得多了。假如说有一天你不想进行版本控制了,直接删除.git文件夹就可以 - gitignore :有时候我们不希望当前目录的一些文件被版本控制,比如一些临时文件或者项目中不需要要的一些文件等,可以在Git库根目录添加.gitignore。 推荐使用gitignore.io,输入你所使用的操作系统、IDEs、编程语言生成。
- git stash
- 我们经常会遇到这样的一些情况,我们正在修改代码的时候,某同事对我喊了一句,嗨 张三你更新下代码,我刚更改了一些重要的功能,你拉下来可以直接使用了。假如说我刚刚修改了一些东西。我就会拉去代码
git pull --rebase
,这个时候会提示你error: Cannot pull with rebase: You have unstaged changes.
,这个时候需要git stash
暂存一下当前的变更,然后再执行刚从的git pull --rebase
。当拉下来代码之后在执行git stash pop
或者git stash apply
git stash apply
区别于git stash apply —index
,后者是完全还原stash前的情况,而前者会把没add的给add了。而git stash pop
后会将stash的内容删除掉
- 我们经常会遇到这样的一些情况,我们正在修改代码的时候,某同事对我喊了一句,嗨 张三你更新下代码,我刚更改了一些重要的功能,你拉下来可以直接使用了。假如说我刚刚修改了一些东西。我就会拉去代码
- git reset revert 和 amend
- 当你想删除某次commit,如果没有push,可以用
git reset commitID
,等同于git reset --soft
和git reset --hard
。还可以git revert
,可以完全回退中间到某个commit,而且可以循环不停地revert。当你不想完全删除commit,只想在那个基础上修改一下,重新提交并覆盖,可以使用git commit --amend
- 如果当前版本控制中的文件还没有被commit,丢掉变更只需要执行git checkout .就可以丢掉对某个文件的变更。
- 如果你已经不小心将错误的提交push到了远程的仓库了。想回退到以前版本。
回退到当前commit的上次提交 git reset --hard HEAD~1 强制提交到远程版本库(!!!这种操作具有一定的危险性) git push origin HEAD --force
- 当你想删除某次commit,如果没有push,可以用
git的三个分区
讲到git一般都会讲git的三个region。工作区、暂存区和版本区。重点:暂存区
- 当对工作区修改(或新增)的文件执行
git add
命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID 被记录在暂存区的文件索引中。 - 当执行提交操作
git commit
时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。 - 当执行
git reset HEAD
命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。 - 当执行
git rm --cached <file>
命令时,会直接从暂存区删除文件,工作区则不做出改变。 - 当执行
git checkout .
或者git checkout -- <file>
命令时,会用暂存区全部或指定的文件替换工作区的文件。 git ls-tree -l HEAD
查看HEAD(版本库中当前提交)指向的目录树 -l参数可以显示文件大小 输出的文件条目从左至右,第一个字段是文件的属性,第二个字段(blob)说明是Git对象库中的一个blob对象(文件),第三个字段是该文件在对象库中对应的ID——一个40位的SHA1哈希值格式的ID,第四个字段是文件大小,第五个字段是文件名。git clean -fd
清除当前工作区中没有加入版本库的文件和目录(非跟踪文件和目录)
开发过程中的git使用及管理
- 从develop上创建一个 Feature branch
git checkout -b myfeature develop
- 当在中途需要引用develop的资源的时候需要合并进来
git rebase develop
-
新特性完成时,可以合并到develop
git checkout develop git merge --no-ff myfeature git branch -d myfeature git push origin develop
git的原理
-
当你在一个新目录或已有目录内执行 git init 时,Git 会创建一个 .git 目录,几乎所有 Git 存储和操作的内容都位于该目录下。如果你要备份或复制一个库,基本上将这一目录拷贝至其他地方就可以了。
➜ .git git:(develop) ls COMMIT_EDITMSG ORIG_HEAD description info refs FETCH_HEAD branches hooks logs HEAD config index objects
- 该目录下有可能还有其他文件,但这是一个全新的 git init 生成的库,所以默认情况下这些就是你能看到的结构。新版本的 Git 不再使用 branches 目录,description 文件仅供 GitWeb 程序使用,所以不用关心这些内容。config 文件包含了项目特有的配置选项,info 目录保存了一份不希望在 .gitignore 文件中管理的忽略模式 (ignored patterns) 的全局可执行文件。hooks 目录保存了钩子脚本。另外还有四个重要的文件或目录:HEAD 及 index 文件,objects 及 refs 目录。这些是 Git 的核心部分。objects 目录存储所有数据内容,refs 目录存储指向数据 (分支) 的提交对象的指针,HEAD 文件指向当前分支,index 文件保存了暂存区域信息。马上你将详细了解 Git 是如何操纵这些内容的。
-
git对象
- Git 是一套内容寻址文件系统。很不错。不过这是什么意思呢? 这种说法的意思是,Git 从核心上来看不过是简单地存储键值对(key-value)。它允许插入任意类型的内容,并会返回一个键值,通过该键值可以在任何时候再取出该内容。
- 红色的叫blob object 它保存文件内容。
- 紫色的叫tree object 它保存这个tree下,所有object的SHA-1哈希值,从而保存目录结构。
- 绿色的叫commit object 它保存这个commit对应tree object的SHA-1哈希值,以及它的提交信息。
- 灰色的是Git References,也就是branch和tag tag和branch的区别在于,branch在不断提交时,会变,而tag不会变。它保存它对应的commit object的SHA-1哈希值,它的文件名即branch或tag的名字。它相当于是给commit起的一个名字。
- Git References之上还有HEAD它一般是保存当前的branch的文件路径。有时它也和Git References 一样,保存commit的SHA-1哈希值,这种HEAD叫detached HEAD。
- 测试git对象
$ mkdir test $ cd test $ git init Initialized empty Git repository in /tmp/test/.git/ $ find .git/objects .git/objects .git/objects/info .git/objects/pack $ find .git/objects -type f 这时候可以看到一些所有的文件在git系统中的存储 $ echo 'test git content' | git hash-object -w --stdin 然后在执行 $ find .git/objects -type f 查看文件的具体内容 $ git cat-file -p {hash-code} 往git系统中添加文件 $ echo 'version 1' > test.txt $ git hash-object -w test.txt 再次添加内容提交 $ echo 'version 2' > test.txt $ git hash-object -w test.txt 查看文件内容 $ find .git/objects -type f 回退到第一个版本 $ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt $ cat test.txt version 1 回退到第二个版本 $ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt $ cat test.txt version 2
-
git对文件夹的存储,tree 对象可以存储文件名,同时也允许存储一组文件。
现在可以用 write-tree 命令将暂存区域的内容写到一个 tree 对象了。无需 -w 参数 ── 如果目标 tree 不存在,调用 write-tree 会自动根据 index 状态创建一个 tree 对象。
$ git write-tree 0155eb4229851634a0f03eb265b69f5a2d56f341 $ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341 $ git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579 $ git write-tree 3c4e9cd789d88d8d89c1073707c3585e41b0e614 $ git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614
-
HEAD标记
- HEAD保存当前branch的文件路径
cat .git/HEAD
- HEAD也可以保存某一个commit的SHA-1哈希值,此时HEAD是处于detached状态
➜ gitShare git:(master) git log ➜ gitShare git:(master) git checkout 24d7773583e0d194945815b1be2ec4cb73ecb94f Note: checking out '24d7773583e0d194945815b1be2ec4cb73ecb94f'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b
HEAD is now at 24d7773... change files - HEAD保存当前branch的文件路径
- Git References
Git Reference是保存commit的SHA-1哈希值
find .git/refs -type f
cat .git/refs/heads/master
git cat-file -p f44f8