workspace 工作区
index 暂存区
repository 本地版本库
remote 远程仓库
本地管理
1、ubuntu下git安装
sudo apt-get install git (linux 上安装方式)
git --version 查看版本
git config -l 查看配置信息
git config --global user.name "your name" (--global参数表示所有仓库均使用该配置)
git config --global user.email "xxx@example.com"
# 其他查看配置相关
git config --global --list # 查看全局设置相关参数列表
git config --local --list # 查看本地设置相关参数列表
git config --system --list # 查看系统配置参数列表
git config --list # 查看所有Git的配置
2、创建版本库
mkdir learngit
cd learngit
创建本地仓库
git init (把该目录变成git管理的仓库)
或 git init 仓库名 # 创建一个新的带Git仓库的项目
git init # 为已存在的项目生成一个Git仓库
3、 将暂存区内容提交到本地仓库
git add filename (文件添加到本地仓库,可以多个文件)
git add 文件名 # 将工作区的某个文件添加到暂存区
git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件
git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件
git add . # 将当前工作区的所有文件都加入暂存区
git add -i # 进入交互界面模式,按需添加文件到缓存区
git commit -m "your commit" (文件提交到本地仓库)
git commit -m "提交说明" # 将暂存区内容提交到本地仓库
git commit -a -m "提交说明" # 跳过缓存区操作,直接把工作区内容提交到本地仓库
4、版本库状态查询
git status (可查看修改过的但未提交的文件)
modified:已添加但修改了的文件
untracked files:未添加的文件
git diff filename (查看修改过的但未提交的文件中修改的内容)
git diff # 是只比较比较工作区和暂存区(最后一次add)的区别,
git diff --cached # 是只比较暂存区和版本库的区别,
git diff HEAD -- filename #是只比较工作区和版本库(最后一次commit)的区别。
git diff 分支名 #工作区与某分支的差异,远程分支这样写:remotes/origin/分支名
git diff 提交id 文件路径 # 工作区某文件当前版本与历史版本的差异
git diff --stage # 工作区文件与上次提交的差异(1.6 版本前用 --cached)
git diff 版本TAG # 查看从某个版本后都改动内容
git diff 分支A 分支B # 比较从分支A和分支B的差异(也支持比较两个TAG)
git diff 分支A...分支B # 比较两分支在分开后各自的改动
5、版本回退或前进
git log <--pretty=oneline> (参数可选,用于查看提交版本的历史记录)
commit 25a984a243b9dfe3db61d80d8830cdf6ec58eb02 (HEAD -> master)
--> commit id(版本号)
Author: xxx <xxx@163.com>
Date: Fri Jun 21 11:01:14 2019 +0800
first version -->版本说明
git log # 查看所有commit记录(SHA-A校验和,作者名称,邮箱,提交时间,提交说明)
git log -p -次数 # 查看最近多少次的提交记录
git log --stat # 简略显示每次提交的内容更改
git log --name-only # 仅显示已修改的文件清单
git log --name-status # 显示新增,修改,删除的文件清单
git log --oneline # 让提交记录以精简的一行输出
git log –graph –all --online # 图形展示分支的合并历史
git log --author=作者 # 查询作者的提交记录(和grep同时使用要加一个--all--match参数)
git log --grep=过滤信息 # 列出提交信息中包含过滤信息的提交记录
git log -S查询内容 # 和--grep类似,S和查询内容间没有空格
git log fileName # 查看某文件的修改记录,找背锅专用
git reset --hard HEAD~n (HEAD表示当前版本,HEAD^表示上个版本,HEAD~n表示前n个版本,用于回退到前面的版本)
git reflog (记录每次使用的命令,可用于查找回退前的commit id,方便前进到该版本)
git reset --hard xxxxx (“xxxxx”表示commit id,可用来回退到或者前进到某个版本)
6、工作区和暂存区
工作区:也就是电脑端存放仓库的文件夹,如learngit
版本库:工作区中隐藏目录“.git”,存放在暂存区、分支、HEAD指针等
暂存区:版本库里存放的一个称为“index”或者“stage”的文件
git add 实际上是将文件修改添加到暂存区
git commit 实际上是把暂存区的所有内容提交到当前分支
7、撤销修改
git管理的是修改,而不是文件
git checkout -- filename (用于撤销工作区的修改)
两种情形:
filename自修改后还未存放到暂存区,撤销修改就回到版本库的状态
filename已经添加到暂存区后又修改,撤销修改就回到暂存区的状态
(可以这么理解:该命令是将暂存区或者版本库的文件代替修改的文件,当暂存区有该文件时,用暂存区的文件覆盖,否则用版本库的文件覆盖。)
git reset HEAD<~n> <file> (用于撤销暂存区的修改,相当于取消之前git add 操作)
git reset --hard HEAD~n (用于撤销版本库的修改,会将所有新添加的文件或更改的文件全部复原)
8、删除文件
- 确定删除时版本库更新:
git rm file (也可用git add file)
git commit -m "xxx"
- 误删时想恢复:
git checkout -- file (恢复版本库的文件到工作区)
远程管理
9、远程仓库GitHub
- 创建SSH Key
在~/.ssh目录生成有效的公私钥信息:
$ cd ~/.ssh
$ ls
# 如果没有.ssh目录,则创建;
# 如果.ssh下有xxx & xxx.pub来命名的一对文件,则.pub为公钥,通常为:id_rsa & id_rsa.pub;
# 如果没有xxx & xxx.pub文件,如下创建:
$ ssh-keygen -t rsa -C "GitHub账号" ,一直Enter下去生成公钥
# 创建期间会有两次密码的输入确认,可为空(推荐);
# 输入后以后的对git的连接确认就需要输入密钥的密码;
# 成功创建后,查看公钥信息, 这里假设生成后的公钥名为:id_rsa.pub
# 公钥信息一般以:ssh-rsa开头,<#user#>@<#hostname#>结尾
$ cat id_rsa.pub
-
网页中登录GitHub,打开“Account settings”,“SSH Keys”页面添加id_rsa.pub文件的内容
-
在GitHub上点击“Create a new repo”按钮,创建新的远程仓库
-
将本地仓库关联到远程仓库
git remote add origin git@github.com:(github用户名)/learngit.git
- 将本地库的所有内容推送到远程库上
git push -u origin master (把当前分支master推送到远程,第一次使用要用-u参数, 为了将本地和远程的分支关联)
10、从远程库克隆
git clone git@github.com:michaelliao/gitskills.git
分支管理
11、创建与合并分支
每次版本库的提交会串成一条时间线,该时间线即是主分支(master分支)。严格来说,HEAD不是指向提交,而是指向master,master才是指向提交的,所以HEAD指向的是当前分支。 当在master分支上的某个节点上创建新的分支dev之后,git会创建一个新的指针叫dev,指向master当前的节点,如果切换到dev分支,则HEAD会指向dev,表示当前分支在dev上。此时如果对版本库做修改不会改变master分支的情况,master指针不变。 如果在dev上的工作完成了,可以把dev合并到master上,方法就是直接把master指针指向dev的当前提交。删除dev分支就是把dev指针给删掉。
master 主分支,记录发布版本
online 线上分支 正在运行的版本
develop 开发分支 用于测试
local 本地分支
- (1)创建分支并切换
git switch -c dev
或者: git checkout -b dev (-b参数表示创建并切换)
或者:
git branch dev (创建分支)
git switch dev (切换分支) 或 git checkout dev
- (2)查看当前分支
git branch (列出所有分支,*表示当前分支)
- (3)合并分支
git checkout master (切换到master分支)
git merge dev (合并dev分支到当前master分支)
git merge 命令用于合并指定分支到当前分支
(4)删除分支
git branch -d dev
12、解决冲突
git merge合并分支时,有时候并不能成功,原因是在两个分支上,同时对同个文件进行了修改,导致合并git并不清楚保留哪个版本。
git status (查看发生冲突的文件)
手动更改发生冲突的文件并保存
git add filename
git commit -m "XXX"
git log --graph --pretty=oneline --abbrev-commit
13、分支管理策略
通常,合并分支时,如果直接用git merge合并,git使用的是“fast Forward”模式,这种模式在删除分支后,会丢掉分支消息。如果强制禁用“Fast Forward”模式,git就会在merge时生成新的commit,这样从分支历史上就可以看出分支信息。
两种模式的情况分别如下图:
git checkout -b dev (创建并切换到dev分支)
git add filename (提交更新的文件到暂存区)
git commit -m "xxx" (提交到版本库)
git checkout master (切换到master分支)
git merge --no-ff -m "xxxxxx" dev (禁用fast forward模式合并,-m 创建新的commit)
git log --graph --pretty=oneline --abbrev-commit (查看分支历史)
实际开发中,应按照几个基本原则进行分支管理:
1.master分支应该是非常稳定的,仅用来发布新版本,不在上面干活
2.在dev分支上干活,dev分支时不稳定的,要发布版本时才将dev合并到master分支上
3.每个人都在dev上干活,每个人都有自己的分支,时不时地往dev分支上合并自己分支。
14、中途修复BUG
软件开发中,如果手头上的工作还没完成,但又需要先将bug修复,则可以按照下面的步骤完成。
git branch (查看当前分支,假设为dev分支)
git status (查看当前分支的情况,显示未提交的内容,但又不能现在提交)
git stash (将当前工作现场保存起来,等以后恢复现场继续工作)
git status (查看当前分支情况,可以看到是干净的,除非有untrack 文件)
git checkout master (假设bug在master分支上)
git checkout -b issue (创建并切换到解决bug的分支issue)
……(此处完成修改bug的工作)
git add filename
git commit -m "fix bug" (提交到版本库新的节点)
git checkout master (切换回master分支)
git merge --no-ff -m "merged bug fix" issue (将issue分支合并到master分支上)
------------------至此,bug已经修复完成
git checkout dev (切换到dev分支继续工作)
git stash list (查看保存好的工作现场,git stash 可连续多次使用)
git stash pop (恢复工作现场并删除stash保存的内容,相当于 git stash apply和 git stash drop)
git stash list (可以看到当前stash已没有内容)
git cherry-pick commit-id (将个commit-id对应的该次提交的修改拷贝到当前分支,不是merge,
同时git会自动给dev分支做一次提交,并且生成新的commit id)
……(此时就可以继续完成工作了)
或者可以使用在dev分支上完成这个修复过程,但仍然还是需要用git stash 保存现场。
15、添加新功能
假如接到了新的任务,需要开发代号为vulcan的新功能,则可按下面步骤来:
git checkout -b feature-vulcan (创建并切换到feature-vulcan分支)
……(新功能添加完成)
git add filename
git commit -m "xxx" (提交到版本库)
git checkout dev (切换回dev分支)
git merge feature-vulcan (合并分支)
git branch -d feature-vulcan (删除分支)
如果在合并前要取消删除feature-vulcan分支,则可以使用下列命令:
git branch -D feature-vulcan (强制删除该分支)
16、多人协作
当从远程仓库克隆项目时,git自动把本地的master分支和远程的master分支对应起来,远程仓库的默认名称为origin。
- 查看远程库信息:
git remote -v
- 推送分支到远程库:
git push origin master (把master分支推送到远程库)
git push origin dev (把dev分支推送到远程库)
需要推送到远程库的分支一般是master分支和员工工作的dev分支,需与远程同步。
- 创建远程分支:
git checkout -b dev /origin/dev
- 推送分支到远程库:
git add filename
git commit -m "xxx" (更新本地仓库)
git branch --set-upstream-to=origin/dev dev (指定本地dev分支与远程origin/dev分支的链接)
git pull (抓取远程库最新代码)
……(有冲突则解决冲突,方法同前述分支管理中的解决冲突方法一致)
git commit -m "XXXXX" (提交)
git push origin dev (将本地dev分支提交到远程dev分支上)
多人协作的工作模式通常是这样: 1.首先,可以试图用git push origin <branch-name>推送自己的修改; 2.如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并; 3.如果合并有冲突,则解决冲突,并在本地提交; 4.没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to=origin/dev dev。
- 将本地未push的分叉提交历史整理成直线:
git rebase
git rebase --continue # 处理完冲突后,继续处理下一个补丁
git rebase --abort # 放弃所有的冲突处理,恢复rebase前的情况
git rebase --skip # 跳过当前的补丁,处理下一个补丁,不建议使用,补丁部分的commit会丢失!
标签管理
17、 标签
标签是版本库的一个快照。
- 创建标签:
git tag <tagname> <commit-id> (在当前分支具体commit-id上打上标签,没有commit-id就默认为当前节点)
git tag -a tagName -m "XXXX" <commit-id> (-a指定标签名,-m指定说明文字)
- 查看所有标签:
git tag
- 查看标签信息:
git show tagName (查看标签为tagName的相关信息)
- 删除标签:
git tag -d tagName
- 推送标签到远程库:
git push origin <tagName>
git push origin --tags (一次性推送所有本地标签到远程)
- 删除远程标签:
git push origin :refs/tags/tagName