动画学git
推荐一个十分好用的学习网站:Learn Git Branching
tip: 可使用show solution
查看参考答案
git配置
git config --global -l # 列出现有的全局配置
git config -l # 列出现有的当前仓库的配置
git config --global user.name Fei-Wang # 设置全局用户名(省略global参数设置当前仓库用户名)
git config --global user.email fei.comm@icloud.com # 设置邮箱
git config --global color.ui true # 让git显示不同的颜色
git config --global core.editor vim # 修改默认编辑器为vim
git config --global credential.helper store # 会在本地生成一个文本用于记录账号密码,下次pull或push输入账号密码之后,再次pull/push操作可以不用输入账号密码
# git换行符配置 https://www.jianshu.com/p/a340848a6ec1
git config --global core.autocrlf input # 提交时转换为LF,检出时不转换
git config --global core.safecrlf warn # 提交包含CRLF换行符的文件会给予警告
# linux下可使用 sed -i 's/\r//' <filename>将文件内的'\r'字符删去
# 当前配置下,pull下来的代码均是LF格式,最好将ide的结尾也设置为LF,否则某些shell文件无法执行
生成ssh密匙
ssh-keygen -t rsa [-C "key name"] # 后跟公匙名称,选填
cat id_rsa.pub
git工作区暂存区和仓库
- 电脑中能看到的文件夹(.git所在目录)为工作区
- .git中又分为暂存区stage和仓库(当前分支)
用到的命令
git diff # 比较暂存区和工作区之间的差异
git diff --staged # 比较暂存区和仓库之间的差异
git diff --cached # 比较暂存区和仓库之间的差异
git reset
git reset --soft
仅重置HEAD指针而不会破坏任何东西(工作区和暂存区均保持原样)- 工作区和暂存区保持git reset之前的状态不变
- 仓库reset到指定commit_id的状态
git reset --mixed
等效于git reset
重置HEAD指针并修改暂存区,工作区进行的实际更改不受影响- 工作区保持reset之前的状态不变
- 暂存区和仓库reset到指定commit_id的状态
git reset --hard
将HEAD指针重置为特定提交ID的最新提交,并删除本地文件更改- 工作区,暂存区和仓库均被reset到指定commit_id的状态
git checkout
git checkout -- <file_name>
放弃工作区所做的修改,已存入暂存区的部分不受影响git checkout .
放弃工作区所有修改,已存入暂存区的部分不受影响
正向操作
- git add
将文件从工作区添加到暂存区,此时使用git diff
来比较工作区和暂存区之间的差异 - git commit
将文件从暂存区添加到仓库(当前分支),此时用git diff -cached
或git diff --staged
来比较暂存区和参考之间的差异
逆向操作
# case 1
vim <file_name> # 工作区已修改,暂存区和仓库未修改
git checkout -- <file_name> # 舍弃工作区的更改
# case 2
vim <file_name>
git add <file_name> # 修改工作区文件并添加到暂存区
git reset --mixed <commit_id> # 从仓库指定id恢复仓库和暂存区
git checkout -- <file_name> # 舍弃工作区的更改
# case 3
vim <file_name>
git add <file_name>
git commit -m "xxx" # 修改工作区文件并添加到暂存区和仓库
git reset --hard <commit_id> # 从仓库指定id恢复仓库,暂存区和工作区
git基础操作
创建git版本库
首先新建一个版本库的目录,然后进入该目录路径,然后执行:
git init
查看仓库状态
git status # 查看仓库中文件的状态
将文件添加到版本库
将文件提交到版本库需要先将文件添加到暂存区,然后提交到仓库
将文件添加到暂存区
git add Readme.md # 将单个文件添加到暂存区
git add . # 将当前目录下所有修改添加到暂存区(除.gitignore中的忽略规则)
将暂存区文件提交到仓库中
git commit -m 'add readme file' # 带评论提交,用于说明提交内容
查看仓库中的具体修改
git diff # 查看工作区和暂存区的不同
git diff --cached # 查看暂存区和版本库的不同,等效于git diff --straged
git diff Readme.md # 查看具体文件的改动
git show <commit_id> # 查看某次commit的修改
查看历史提交记录
git log [file_name] # 显示[某个文件]所有的历史记录
git log --pretty-oneline [file_name] # 单行[某个文件]显示历史记录
git log -n [file_name] # 显示[某个文件]最近n行记录
git log -p [file_name] # 显示[某个文件]每次提交的diff
git show <commit_id> [file_name] # 查看[某个文件]某次提交的变化
git log remotes/origin/develop # 查看远程仓库develop分支的log,使用前先fetch一下
在git log的输出中,包括了每次提交的commit_id,是一串hash后的字符串
git取消文件追踪/文件重命名
git rm [--cached]/[--f] [-r] <file> # --cached: 取消追踪但不删除本地文件,--f: 取消追踪并删除本地文件
# 若是目录,则需要添加-r选项
# 类似的,可以使用git mv命令来重命名文件
git mv <file_name> <new_file_name> # 变更追踪文件的文件名
版本回退
有了git log的历史提交记录,就可以通过回退到当时的代码版本
git reset --hard HEAD^ # 回退到上一个提交版本
git reset --hard HEAD~2 # 回退到上上个提交版本 等价 HEAD^^
git reset --hard 'commit_id' # 回退到commit_id指定的提交版本
回到未来某个提交
当回到历史版本后,在通过git log
后无法显示在这之后的提交信息,此时可以通过git reflog
来查看、切换
git reflog
git reset --hard 'commit_id'
撤销修改
撤销工作区中的修改
git checkout -- Readme.md # 撤销工作区中的单个文件的修改
git checkout -- . # 撤销当前目录下所有文件的修改
撤销进入暂存区的修改
git reset HEAD Readme.md # 将某个文件恢复到HEAD提交的版本
stash暂存
git stash # 将当前开发到一半的工作区push_back到stash list并编号
# 此时再查看git status则发现工作区是干净的
git stash list # 查看保存的stash列表
git stash show [-p] <n> # 查看stash list中编号为n的stash与当前最新的commit之间的diff
git stash pop # 弹出栈顶的修改内容,同时stash list的size-1
git stash apply <n> # 应用stash list中编号n的stash,stash list的size不变
git stash drop <n> # 删除stash list中编号n的stash
分支管理
查看分支
git branch # 查看本地分支信息
git branch -v # 查看相对详细的本地分支信息
git branch -av # 查看包括远程仓库的分支信息
git branch -vv # 查看详细分支信息(可看到当前分支与对应的远程追踪分支)
创建、切换分支
git branch dev # 创建一个名为dev的开发分支
git checkout dev # 切换到dev分支
git checkout -b dev # 创建dev分支,并切换到该分支上
git checkout -t origin/dev # 本地没有dev分支,云端有该分支,创建并切换
git push -u origin <branch_name> # 本地有分支,远程无该分支,推送新建分支到远程仓库
合并分支
当修复了bug,或者开发了新特性,就需要把分支上的修改合并到主分支
git merge dev # 将dev分支上的修改合并到当前分支
git rebase dev master # 将dev分支上的修改合并到master分支
git cherry-pick <commit_id>... # 将多个commit复制到当前HEAD下面
git rebase -i HEAD~3 # 交互式的修改(合并,调整顺序,删除等)最近的三个commit
重命名分支
git branch -m dev develop # 将dev分支重命名为develop
git branch -m develop # 将当前分支重命名为develop
重命名本地分支和远程分支名称:
git branch -m <old_branch> <new_branch> # 本地分支重命名
git push origin :<old_branch> # 删除对应的远程分支
git push --set-upstream-to origin <new_branch> # 将新建的分支推送到远程
删除分支
合并分支后,这个分支就不需要了,可以将其删除
git branch -d develop # 删除develop分支
比较两个分支间的差异
# 查看branch1与branch2不同的commit记录
# 注意commit 后面的箭头,根据我们在 –left-right branch1…branch2 的顺序,左箭头 < 表示是 branch1 的,右箭头 > 表示是branch2的
git log --left-right branch1...branch2
# 显示branch1与branch2中文件差异
git diff branch1 branch2 [--stat]
git diff branch1 branch2 path_to_file
远程仓库
从远程仓库克隆
git clone https://github.com/Fei-Wang/Fei-Wang.github.io.git # 通过https协议克隆
git clone git@github.com:Fei-Wang/Fei-Wang.github.io.git # 通过ssh协议克隆
git clone <git_address> -b <branch_name or tag_name> # 克隆指定分支或tag
推送本地到远程
git push origin master # 将当前branch推送到origin对应branch
git push -u origin master # 若远程有多个主机,可使用-u参数将本地与origin主机之间建立追踪关系,之后直接使用git push即等效于git push origin master
从远程仓库获取最新内容
在多人协作中,在推送前,需要先获取远程仓库的最新内容
git fetch origin master # 仅获得远程仓库的更新内容,不会自动合并
git pull origin master # 获得更新内容后自动合并,相当于git fetch + git merge
查看远程仓库与本地代码的区别
在多人协作中,在推送时可能会出现本地修改与远端冲突,不能自动merge,需要手动调整
# 当前为develop分支
git fetch origin develop
git diff develop origin/develop # 比较云端develop分支与本地develop分支代码
查看远程仓库信息
git remote [-v] # 显示远程仓库信息
git remote remove origin # 删除名为origin的远程仓库
git remote add origin [url] # 添加名为origin的远程仓库
关联本地分支和远程分支
git branch -u origin/dev # 将当前分支与远程的dev分支建立联系,之后便可直接使用git push/pull命令来更新本地分支与相关联的分支
git branch --set-upstream-to origin/dev # 与上一条命令等效
git branch --unset-upstream # 删除当前分支关联的云端分支
标签管理
通常在代码发布的时候打一个tag,tag只是某个commit的快照,方便回溯。
创建标签
git tag <tagname>
git tag -a <tagname> -m "comment" <commit_id> # -a指定标签名,-m添加备注信息,'commit_id'指定打标签的提交id
查看已有标签
git tag # 查看本地仓库中的所有tag
git tag -l "v1.*" # 加上-l命令可以使用通配符过滤tag
查看具体标签信息
git show <tagname> # 查看tag详细信息,包括commit号等
切换到某个tag
跟branch
一样,可以直接切换到某个tag
中去。这时候git会提示detached HEAD
,表明当前不属于任何分支,处于游离状态,此时对代码做的修改不会保存(可正常git add
, git commit
,但再次checkout
后便会恢复tagname
原始的状态),若需要基于某个tag
修改代码,可以基于tag
创建一个分支。
git checkout <tagname> # 切换至某个tag,此时处于游离状态
git checkout -b <branch_name> <tagname> # 基于tag创建一个新的分支
推送标签到远程仓库
git push origin <tagname> # 推送单个标签到远程仓库
git push origin --tags # 推送所有标签到远程仓库
删除本地标签
git tag -d <tagname>
删除远程标签
git push origin :refs/tags/<tagname>
git push origin --delete <tagname>
git push origin :<tagname>
git submodule
参考这里
更新子模块
git submodule update --init --recursive # 更新当前目录下的所有子模块