git
[TOC]
设置
git config --global user.name ""
git config --global user.email ""
基本操作
- 初始化git库:
git init
- 添加文件到分支:
git add filename
git commit -m "statement about the change"
- 查看仓库状态:
git status
,检查仓库各分支状态 - 修改已提交到分支的文件后,使用
git add
保存修改,使用git checkout
放弃修改。 - 使用
git add
暂存更改后,可以使用git reset
取消暂存。
如果有多个文件,并且不同文件间有的是为了同一个功能,有的不是,最好的是将他们分别暂存提交,能更容易的调优每一次提交。
- 修改git commit中使用的编辑器:
git config --global core.editor vim
- 在暂存了某次修改,但是并未提交,后又修改了文件,那么提交只能提交已经暂存的修改。
使用
git .
来添加当前文件夹中所有子文件夹和文件。
- 使用git log查看提交过的记录
git log
:一条提交记录分多行展示:第一行是提交的唯一hash值;第二行是作者,第三行是提交时间,然后是提交的说明
- 使用
git log --pretty=oneline
使得每条记录作为一行输出- 使用参数
--max-count=2
表示从记录中选择最新的两条记录输出- 参数
--since="5 minutes ago"
5分钟前到现在的提交记录- 参数
--until="5 minutes ago"
输出从仓库建立到5分钟前提交的记录- 参数
--author="username"
输出username用户提交的记录- 参数
--merge
输出只有merge的提交记录- 使用
man git-log
查看log相关的参数- 使用
--graph
使用ascll图形布局显示提交树- 使用
--date=short
保留日期格式更好且更短
git log的pretty 的format参数值可以使用
- %h:commit的hash时间
- %cd:create datetime创建时间
- %s:statement注释
- %an: author name
为常见命令设置别名
在当前用户home目录$HOME
(linux使用命令 cd ~
进入)中,有git的配置文件.gitconfig
输入配置如下:
[alias]
co = checkout
ci = commit
st = status
br = branch
hist = log --pretty=formate:'%h %ad | %s%d [%an]' --graph --date=short
type=cat-file -t
dump = cat-file -p
设置shell别名:
alias gs='git status '
alias ga='git add '
alias gb='git branch '
alias gc='git commit'
alias gd='git diff'
alias gco='git checkout '
alias gk='gitk --all&'
alias gx='gitx --all'
alias got='git '
alias get='git '
如果需要使用go语言,需要将上述alias中
go
改为gco
比较好。gs
可能与linux ghostscript冲突。需要注意!
标记版本
使用git tag v1
(其中v1表示版本号)给当前版本打上标签
使用git checkout
转到其他版本,然后使用git tab versionnumber
给转到的版本打上标签。
使用
git checkout v1^
表示v1上一个版本。或者使用git checkout v1~1
。
撤销更改
使用git checkout master
跳转到master上面(不然之后操作的时候就把当前master的记录给覆盖掉了)
- 没有暂存 若本地更改没有使用
git add
暂存到仓库,那么可以使用git checkout filename
将文件转到之前的master版本保存的记录。 - 已经暂存 使用
git reset HEAD filename
去取消暂存,但是reset命令不会更改文件内容, 文件中已经修改的内容还在文件中。如果想将文件中的内容恢复到原来状态,可以使用git checkout filename
- 已经提交 使用
git revert HEAD
(会自动打开commit编辑界面)或者git revert --no-edit
(不会打开编辑器),将提交版本回到上一个版本。也可以就爱那个HEAD
部分使用更早版本的hash值代替,直接回到更早的版本。 - 从分支中移除提交
revert
命令是撤销仓库中任意提交的命令。reset
命令是重置命令,当给定 一个提交的 引用(标签,hash值, 分支)时, reset命令将: - 重写当前分支到指定的特定提交
- 重置暂存区到匹配的特定提交(可选)
- 重置工作目录到匹配特定的提交(可选)
可以使用git reset --hard v1
将分支中中v1版本以后的提交全部移除。 其中--hard
参数表示应当更新工作目录(文件和文件夹)以便与新的分支头保持一致。
使用git hist --all
可以看到之前的所有提交记录,什么文件都没有丢。被移除的内容会一直保存在仓库中,知道运行垃圾回收软件。
重置一般是安全的,但是如果分支是共享在远程服务器上的,那么reset可能会导致用户共享的分支混乱
在上例中,可以通过git tag -d tagname
移除标签,让仓库回收删除的分支(回收垃圾)。 回收后使用git hist --all
,在分支的历史记录中就看不到移除的分支信息了,好像那个分支从未提交一样。
修改提交
在提交了一个版本后,发现提交的版本忘了一项纪录,但是又不想提交两次,则可以在修改/添加好要修改的记录后,使用git add filename
将添加/修改的file暂存,然后使用git commit --amend -m "comment"
命令,替换掉上次的提交记录。
移动文件
在项目需要调整文件结构的时候,需要移动文件。 使用git mv
命令移动文件。
.git 目录
使用ls .git
查看.git
目录下文件
$ ls .git
COMMIT_EDITMSG ORIG_HEAD hooks logs rr-cache
HEAD config index objects
MERGE_RR description info ref
对象存储
对象存储在objects文件夹中,文件爱你都经过压缩处理。
$ ls -C .git/objects
09 1f 27 43 69 83 97 af e4 info
0f 22 28 58 6b 94 9c b5 e7 pack
11 24 32 59 78 96 a1 c4 eb
$ ls -C .git/objects/09
6b74c56bfc6b40e754fc0725b8c70b2038b91e 9fb6f9d3a104feb32fcac22354c4d0e8a182c1
在objects目录的子目录中,每个文件都是用38字符命名的文件。
配置
配置在.git/config
文件中,该文件是项目级配置文件。在这儿的配置条目将覆盖你的主目录中.gitconfig
文件中的配置条目。
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
分之与标签
$ ls .git/refs
heads
tags
$ ls .git/refs/heads
master
$ ls .git/refs/tags
v1
v1-beta
$ cat .git/refs/tags/v1
1f7ec5eaa8f37c2770dae3b984c55a1531fcc9e7
.git/refs/heads
文件夹保存所有的分支,文件名为分支名。文件中的内容为该分支最后一次提交的hash值。 .git/refs/tags
文件夹保存标签。每个标签文件中是标签对应的提交版本hash值。
HEAD文件
$ cat .git/HEAD
ref: refs/heads/master
HEAD文件保存当前分支的引用。
分支
创建分支
使用git checkout -b branchname
创建并切换到分支。 它是git branch branchname
和git checkout branckname
的简写。
导航分支
使用git checkout branchname
切换分支,在不同分支下,相同文件的内容可能会不一样。
合并分支
当出现多个分支,master开始修改文件,那么在git log --graph --all
就可看到版本分叉。 此时可能需要将多个分支合并 使用git merge branchname
将当前分支与branchname分支合并到当前分支。
将master分支修改后,bak分支不变,merge master分支到bak 可保持bak与master的兼容性。
冲突和解决冲突
- 合并 当master分支和greeter分支一致,修改master分支中与greeter分支中共有的文件时,会出现冲突。
冲突原因:greeter有一个文件的版本,master有一个版本,合并的时候怎么选择?
使用编辑器打开冲突文件,手动解决冲突。
解决冲突后,将greeter merge到master,执行的是快速合并,因为master头是分支greeter头的祖先,可以进行快速合并,当快速合并时,分支指针简单的前进到与greeter分支相同的提交处。
- 变基 可以使用
git rebase master
将master分支的所有的更改和greeter分支更改合并到greeter分支。并且提交树会被重写,以至于master分支称为greeter分支的一部分。
一般在公有仓库使用合并,在短期本地项目中使用变基。 变基会丢失历史提交信息!!! 变基会造成老版本丢失(垃圾回收时)
clone
使用git clone from to
可将from仓库克隆到to仓库。这两个仓库几乎一样,除了to仓库多了一个origin
分支。
使用git remote
查看远程仓库的列表 使用git remote show origin
即可查看origin
的信息。
查看远程分支
使用git branch
发现只有master分支列出来了。【git branch
默认只会列出本地分支】
使用git branch --all
列出全部分支,此时可以看到从远程仓库中克隆的分支。
取得远程更改
使用git fetch
从远程仓库拉下更改,拉下的更改是合并到了origin/master
分支【即origin仓库的master分支】,但是它并没有将拉下的更改整合到克隆仓库的分支中。
git fetch
从远程仓库中取得新的提交,但是它不会将这些提交合并到本地仓库中。
合并远程更改
使用git merge origin/master
合并origin/master分支到本地分支。
上述的拉下并合并可以由操作
git pull
完成,git pull
等价于git fetch
和git merge
添加跟踪分支
添加远程分支到本地分支。git brach --track greeter origin/greeter
操作后,在克隆仓库中就可以看到远程仓库的greeter分支了。
推送更改到远程分支
使用git push origin master
,将本地仓库推送到远程仓库的master分支。
此时如果在远程仓库包含工作目录,而且使用
git checkout master
正在master分支中。会报错“git 不允许push 操作更新到non-bare 仓库,因为这样会导致remote仓库的索引(index)和工作树(work tree) 与你push的不一致”。 ** 解决的办法**:最好是将更改push到裸仓库;也可将远程仓库checkout到别的分之下。这样就可以push到远程仓库的master分支了。
裸仓库
裸仓库指的是没有工作目录(工作目录指需要做版本管理的文件目录)的仓库,即只有原仓库中的.git
目录下的文件。
裸仓库一般用于共享。方便合作开发。 比如多人开发: A:裸仓库 B:仓库1 C:仓库2 B修改后,push到A,C获取更改只需要从A中获取更改,并与自己的分支合并。
使用git clone --bare hello hello.git
创建裸仓库hello.git
。
托管仓库
使用git daemon --verbose --export-all --base-path=.
使用git共享自己的仓库。
如果想使用远程push,托管的仓库必须设置参数
--enable=receive-pack