修改配置
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
// git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
// 每个仓库的Git配置文件都放在.git/config文件中
创建本地库
$ mkdir learngit // 创建一个目录
$ cd learngit // 进入
$ pwd // 查看当前地址
$ git init // 仓库初始化(生成 .git)
往本地库添加内容
$ git add readme.txt // 添加
$ git add -f App.class // 强制添加,不受.gitignore 限制
$ git commit -m "wrote a readme file" // 提交
$ git add . //提交被修改的和新建的文件,但不包括被删除的文件
$ git add -u // 更新所有改变的文件,即提交所有变化的文件
$ git add -A // 提交已被修改和已被删除文件,但是不包括新的文件
查看往期提交情况
$ git log // 看日志
$ git log --pretty=oneline // 加参数减少显示内容
$ git log -1 // 最后一次提交信息
$ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
// 通过别名更新git log 处理(非常好用哦)
回退到之前版本
$ git reset --hard HEAD^
// HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
$ git reset --hard 1094a // 回退某一个提交
$ git reflog //记录你的每一次命令
库状态查询
$ git status // 显示库状态
$ git diff HEAD -- readme.txt // 查看工作区(--)和版本库(HEAD)里面最新版本的区别
丢弃修改
$ git checkout -- readme.txt // 此时如果stage有内容,将stage内容恢复到工作区,要是stage区没有, 从仓库区恢复到工作区--很(重要,没有--,就变成了“切换到另一个分支”的命令)
$ git reset HEAD readme.txt // 可以把暂存区的修改撤销掉(unstage),不影响工作区
$ git reset --hard HEAD^ // 已经提交了不合适的修改到版本库时,撤销本次提交, 这个时候 stage 跟工作区都会回退到 HEAD^
删除文件
$ git rm test.txt // 删除工作区的某个文件
// 要是删错了,可以$ git checkout -- test.txt, 其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”
本地仓库与远端仓库连接(添加远程库)
$ git remote add origin git@github.com:zxf/learngit.git // 与远端库建立联系,在此之前先将本地的SSH key 添加到远端仓库上
$ git remote // 查看远程仓库信息
$ git remote -v // 显示更详细的信息
$ git push -u origin master // 将本地内容push到远端master 分支
// 由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
$ git push origin master // 从现在起,只要本地作了提交,就可以通过该命令同步远端master
$ git remote rm origin // 删除已有的GitHub远程库
tips:
- 要关联一个远程库,使用命令
git remote add origin git@server-name:path/repo-name.git
- 关联后,使用命令`git push -u origin master``第一次推送master分支的所有内容;
- 此后,每次本地提交后,只要有必要,就可以使用命令
git push origin master
推送最新修改
tips:
- 本地库可以同时关联多个远端库
git remote add github git@github.com:zxf/learngit.git
git remote add gitee git@gitee.com:zxf/learngit.git
git push github master
git push gitee master
本地仓库与远端仓库连接(从远程库克隆)
$ git clone git@github.com:zxf/gitskills.git // 克隆一个本地库
tips:
- 使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。ssh 协议最快。
分支
$ git checkout -b dev // -b参数表示创建并切换,相当于以下两条命令:
$ git branch dev // 创建dev分支
$ git checkout dev // 切换到dev分支
$ git branch // 查看当前分支
$ git merge dev // 合并dev分支到当前分支
$ git branch -d dev // 删除dev分支
$ git switch -c dev // 创建并切换到新的dev分支
$ git switch master // 切换到master分支
$ git log --graph // 可以看到分支合并图
$ git log --graph --pretty=oneline --abbrev-commit // 简约分支合并图
$ git merge --no-ff -m "merge with no-ff" dev // 不用ff方式合并, 能保留分支修改记录
tips:
- 查看分支:
git branch
- 创建分支:
git branch <name>
- 切换分支:
git checkout <name>
或者git switch <name>
- 创建+切换分支:
git checkout -b <name>
或者git switch -c <name>
- 合并某分支到当前分支:
git merge <name>
- 删除分支:
git branch -d <name>
fast-forward:(同base的情况下可以ff)
–no-ff : (再做一次提交, 生成一个节点,保留dev 开发痕迹)
普通合并:
开发建议:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了
临时bug 处理/ feature添加
保存当前工作现场, 创建其他分支处理bug/feature, 待问题解决后从保存得到现场中恢复,继续工作,记得将修改同步到当前工作现场
$ git stash // 把当前工作现场“储藏”起来,等以后恢复现场后继续工作
$ git stash list // 查看“储存”列表
$ git stash apply // 恢复,但是恢复后,stash内容并不删除,你需要用下面命令:
$ git stash drop // 来删除;
$ git stash pop // 恢复的同时把stash内容也删了
$ git stash apply stash@{0} //恢复指定的stash
$ git cherry-pick 4c805e2 // 复制一个特定的提交到当前分支,避免bug修复来回改(这里要是有冲突会怎么样?)
$ git branch -D feature-vulcan // 强行删除分支(未合并分支会提醒)
多人协作
$ git remote // 查看远程仓库信息
$ git remote -v // 显示更详细的信息
$ git push origin master // 推送到远程origin仓库下的master分支
$ git pull origin master // 如果push不成功,有冲突, 那么先pull一下, 解决冲突再push
$ git checkout -b dev origin/dev // 创建远程origin的dev分支到本地
$ git branch --set-upstream-to=origin/dev dev // 指定本地dev分支与远程origin/dev分支的链接
$ git rebase
// rebase操作可以把本地未push的分叉提交历史整理成直线;(将本地挪动位置, 放在他人提交之后)
// rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
tips:
- 但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
master
分支是主分支,因此要时刻与远程同步;
dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
bug
分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug(这个应该通过bug管理系统处理,所以也是不需要的);
feature
分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发(一般各自完成模块, 完成后统一push到dev模块, 所以也不需要);
总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!
tips:
- 查看远程库信息,使用
git remote -v
; - 本地新建的分支如果不推送到远程,对其他人就是不可见的;
- 从本地推送分支,使用
git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交; - 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致; - 建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name
; - 从远程抓取分支,使用
git pull
,如果有冲突,要先处理冲突。
标签
打标签是为了更好管理迭代发布
$ git branch // 查看branch
$ git checkout master // 切换到master分支
$ git tag v1.0 // 给该分支(master)打一个新标签
$ git tag // 查看所有标签(标签不是按时间顺序列出,而是按字母排序的)
$ git tag v0.9 f52c633 // 找到对应的提交并打上标签
$ git show v0.9 // 查看标签信息
$ git tag -a v0.1 -m "version 0.1 released" 1094adb // 创建带有说明的标签,用-a指定标签名,-m指定说明文字(最好给标签带上一个说明)
$ git tag -d v0.1 // 删除标签 未推送的标签好删除, 推送到服务的标签删除比较麻烦, 得先本地删除,然后push
$ git push origin :refs/tags/v0.9 // 删除远程标签
$ git push origin v1.0 // 推送某个标签到远程
$ git push origin --tags // 一次性推送全部尚未推送到远程的本地标签
tips:
- 标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
- 命令git
tag <tagname>
用于新建一个标签,默认为HEAD,也可以指定一个commit id; - 命令
git tag -a <tagname> -m "blablabla..."
可以指定标签信息; - 命令
git tag
可以查看所有标签。 - 命令
git push origin <tagname>
可以推送一个本地标签; - 命令
git push origin --tags
可以推送全部未推送过的本地标签; - 命令
git tag -d <tagname>
可以删除一个本地标签; - 命令
git push origin :refs/tags/<tagname>
可以删除一个远程标签。
.gitignore
必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,每次git status都会显示Untracked files,这个时候就可以用 .gitignore 解决
$ git check-ignore -v App.class // 检查文件是否被.gitignore了
$ git add -f App.class // 被忽略的文件可以通过-f 强制添加
tips:
- 忽略文件的原则是:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
- 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
# Windows 自动生成的垃圾文件:
Thumbs.db
ehthumbs.db
Desktop.ini
# Python/JavaScript 编译产生的文件或目录:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
# 自己定义的文件:
db.ini
deploy_key_rsa
# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class
# 不排除.gitignore和App.class:
!.gitignore
!App.class
别名使用
$ git config --global alias.st status // 别名命令,将 git status 变成 git st,方便执行
$ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
tips:
别名放在.git/config文件中,就在[alias]后面,要删除别名,直接把对应的行删掉即可。
github 使用 (gitee类似)
- 在GitHub基于目标库 fork 出一个自己的远端库
- 从自己的远端库 clone 出一个到自己得到本地库
- 本地库处理内容并push到远端库
- 在GitHub上发起一个pull request,看目标库管理者是否接受
- 想要实时同步目标库到工作库&远端库的话
- 先本地库git remote 目标库
- git pull获取目标库更新本地库
- git push 到自己的远端库
git服务器搭建
强烈推荐用Ubuntu或Debian
一:安装git // $ sudo apt-get install git
二:创建git 用户 // $ sudo adduser git
三:创建证书登录,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个
四:初始化git仓库 // $ sudo git init --bare sample.git (Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾)
六:把owner改为git // $ sudo chown -R git:git sample.git
七:通过编辑/etc/passwd 禁止git用户登录shell,改为git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell, 这样,git用户可以正常通过ssh使用git,但无法登录shell
八:本地clone试试 // $ git clone git@server:/srv/sample.git
tips:
- 搭建Git服务器非常简单,通常10分钟即可完成;
- 要方便管理公钥,用Gitosis;
- 要像SVN那样变态地控制权限,用Gitolite。
问题解决
1: Error:ssh连接时,‘Please make sure you have the correct access rights
and the repository exists.’。原因:ssh 不通。解决:本地ssh key copy到对应远端仓库才能用ssh。
2: Error:git pull/merge/‘refusing to merge unrelated histories’。 原因:两个分支没有取得关系。 解决:git pull geelib master --allow-unrelated-histories
。
示例
- 创建空白文件夹:mkdir project
- 克隆已有代码仓库:git clone 代码地址
- 拉取制定分支:git checkout -b dev origin/feature/dev