Git
Git特点:
- 在2002由Linus花了两周写的,用在Linux版本维护,后来由Linux社区高手维护
- git是维护修改
- git是分布式版本控制
在此之前,近期有发现了一个学习git比较有意思的站点,推荐新手同学可以试试: learngitbranching.js.org
Git使用
I. 创建:
本地:
git init
- 效果:
创建版本库(.git)
远程:
git remote add [<远程库分支名>] [<远程库地址>]
- 效果: 关联本地库与远程库
git clone [<远程库地址>]
- 效果: 克隆远程库到本地(包括工作区与版本库)(一般而言只checkout了远程origin分支到本地master分支).
git clone -b <远程分支名> <远程库地址>
- 效果: 克隆远程分支到本地(本地分支名和远程分支名相同).
分支:
git branch [<分支名>]
- 效果: 1 创建分支; 2 若没有提供<分支名>直接
git branch
将列出所有分支,并在当前分支前面显示*
git checkout [-b] [<分支名>]
- 效果: 1 切换到<分支>(HEAD指针指向[分支]); 2 若有
-b
则表示创建并切换到<分支>
git checkout [-b] [<本地分支名>] [<远程分支名>]/[<本地分支名>]
- 效果: 创建远程分支到本地分支
II. 提交:
git add [file]
git rm [file]
- 效果: 将修改/删除添加到版本库中的
stage
的暂存区
git commit -m [<描述>]
- 效果: 把暂存区的内容提交到当前分支
git push [<远程库分支名>] [<本地分支名>]
- 效果: 把分支内容推到远程库相对应的分支上
合并:
推荐merge工具: p4Merge
git merge [<目标分支>]
- 效果: 与目标分支合并(如果默认优先Fast-forward说明是快进模式(很快的合并)(ps: 该模式如果删掉分支,会丢掉分支信息))
git merge --no-ff -m [<描述>]
- 效果: 跳过Fast forward模式,保留版本库中分支结构(
git log --graph
)
git fetch <远程仓库名> <远程分支名>(:本地新分支名)
- 效果: 从远程的仓库(通常是
origin
)的分支下载最新版本到 本地的新的分支上,如果不提供默认:下载到 本地分支远程仓库/分支名 (例子:origin/master
) 上。
git fetch
和git pull
- 区别:
git pull
=git fetch
+git merge
1 |
|
删除:
git branch -d [<分支名>]
- 效果: 删除目标分支(
-D
大写D是强行删除(未进行merge就直接删除时使用))
撤销:
git reset [<版本参数>] [<文件名>]
- 效果: 从暂存区撤销某文件的提交
git checkout -f
- 效果: 撤销未提交的文件
III. 状态:
git status
- 效果: 显示状态
git log -1
- 效果: 查看最后一次提交
git remote
- 效果: 远程库信息(
-v
查看详情(fetch地址与push地址))
git stash
- 效果: 存储当前工作现场(通常用在:用于工作一半,想要切换分支的时候)
存储现场:
git stash list
- 效果: 所有储存的工作现场列表
git stash apply [<现场id>]
- 效果: 应用现场id指定的现场
git stash stop [<现场id>]
- 效果: 删除现场id指定的现场
git stash pop
- 效果: 应用最早的现场,并删除它
IV. 对比:
git diff [<文件名>]
拓展
git diff HEAD -- [<file>]
- 效果: 工作区和版本库分支里的最新版本对比
V. 日志:
git log
- 效果: 查看git日志
git log -p
- 效果: 查看git并且显示具体文件修改点
git commite --amend -m [msg]
- 效果: 修改上次提交的commit message
查看历史git命令(可以用来找commit id
)
git reflog
简化:
git log --pretty=online
查看分支合并图:
git log --graph
VI. 回退代码:
git reset --hard [commit id/版本参数]
版本参数定义:
HEAD
表示当前版本,上一个版本:HEAD^
,上n个版本就是加n个^
或者HEAD~[n]
拓展:
git checkout -- [<文件名>]
- 效果:
1 |
|
git reset HEAD [file]
- 效果: 撤销
stage
暂存区中[file]文件的修改
VII. 冲突
修改好冲突文件后,直接重新提交即可.
冲突文件一般的表示:
1 |
|
强烈推荐mergetool: p4merge
VIII. 同步远程
git pull
- 效果: 同步远程库(如果提示
no tracking information
,说明本地分支与远程分支的链接关系没有创建,用命令git branch --set-upstream [<本地分支名>] [<远程分支名>]/[<本地分支名>]
进行创建链接)
IX. 标签
创建
git tag [<标签名>] [<commit id>]
- 效果: 给对应commit id打上标签,如果不提供comit id,默认给最新一次提交打上标签
git tag -a [<标签名>] -m [<标签描述>] [<commit id>]
效果: 给对应commit id打上标签,并给标签加上了描述,如果不提供comit id,默认给最新一次提交打上标签
git tag -s [<标签名>] -m [<标签描述>] [<commit id>]
效果: 给对应commit id打上标签,并给标签加上了描述,并且加上PGP签名,如果不提供comit id,默认给最新一次提交打上标签
显示
git tag
- 效果: 查看所有标签
git show [<标签名>]
- 效果: 显示标签那次提交的信息
删除
git tag -d [<标签名>]
- 效果: 删除标签
远程
git push [<远端仓库名>] [<标签名>]
- 效果: 将标签推送到远程库分支
git push [<远程库分支名>] --tags
- 效果: 将本地所有标签推送到远程库分支
git push [<远端仓库名>] :refs/tags/[<标签名>]
- 效果: 将删除的标签同步到远程库分支
X. 子模块
1. 添加子模块
1 |
|
2. 修改子模块
1 |
|
3. 更新子模块
方式一
在父项目目录下运行: git submodule foreach git pull
方式二
进入对应的子项目目录: git pull
4. 拉取存在子模块的项目
方式一
在父项目目录下运行: git clone [<远程库地址>] --recursive
方式二
1 |
|
5. 删除项目中的子模块
1 |
|
XI. 其他需要注意的
1. 由于Mac下文件名大小不敏感,造成git下如果改了名字,git不识别有变化,因此改名字需要使用下面命令
git mv --force myfile MyFile
2. 如果需要修改提交过的历史用户资料
3. 修改Commit Message
当然若修改的那个Commit已经在远端,需要
git push --force
覆盖远端。
- 如果只是修改最后一条Commit Message:
git commit --amend
- 如果需要修改更早之前的一些Commit Message:
git rebase -i [<Commit Id>]
XII. Git 配置
配置文件
局部: 项目工作区.git/config
全局: ~/.gitconfig
命令配置
git config --global color.ui true
- 效果: Git会适应当地显示不同颜色
忽略特殊文件
在项目工作区根目录下直接创建.gitignore
文件然后望里面添加文件名即可
可以参考: https://github.com/github/gitignore
别名配置
git config --global alias.[<别名>] [对应命令]
推荐别名:
1 |
|
XIII. GitHub
fork同步问题
A项目是B项目的fork,如果同步B项目的更新:
1. 先把B clone到本地
1 |
|
2. 再cd到本地B的目录,把A作为一个remote加到本地的B中(一般命名为upstream)
1 |
|
3. pull另一个A的remote(upstream)的相应分支(比如master)就可以
1 |
|
4. 最后push回github的B_REPOSITORY
1 |
|
XIV. 其他疑难问题
调用git fetch
的时候,出现:
1 |
|
你执行git fack
会发现一堆的挂起的dangling blob xxxxxxxxxxxxxxx
此时只需要: gc 下 git gc --prune=now