前言
版本控制系统分类 | 特点 | 代表 |
---|---|---|
集中式版本控制系统 | 版本库是集中存放在中央服务器,缺点:必须联网从中央服务器取得最新的版本后才能工作 | CVS、SVN |
分布式版本控制系统 | 根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库 | Git(目前最先进) |
Git 最核心的一个概念就是工作流,分为下面三个阶段:
- 工作区(Workspace):电脑中实际的目录。
- 暂存区(Index):类似于缓存区域,临时保存你的改动。
- 仓库区(Repository):分为本地仓库和远程仓库。
Git 库所在的文件夹中的文件大致有4种状态:
Tip1: 不懂的语法、命令、参数,去官网查询
Tip2: 快速学习,廖雪峰Git教程
一、常用命令大纲
命令 | 作用 |
---|---|
git verb --help或 git verb -h | 无需联网,查看动作的用法 |
git status | 查看状态 |
git init | 初始化,纳入版本控制系统 |
git add file或 git add . | 添加到暂存区变成版本跟踪状态 |
git rm --cached file | 移除暂存区变成版本未跟踪状态 |
git restore file | 修改后的文件丢弃修改 |
git restore --staged file | 变成未暂存的状态 |
git diff或 git diff --staged | 查看未暂存或已暂存的变化内容 |
git commit -m " "或 git commit -a -m " " | 提交到版本库 |
git mv filename1 filename2 | 重命名文件且将其暂存 |
git log --pretty=oneline -2 | 显示提交日志 |
git add . 后git commit --amend -m | 既可以对上次提交的内容进行修改,也可以修改提交说明 |
git reset --hard HEAD~3或 git reset --hard HEAD commit版本号 | 回到某个版本 |
git relog --pretty=oneline -2 | 就算回退版本后也能显示所有提交日志 |
git rm file且 git commit " " | 删除文件并记录此次删除操作 |
git branch | 查看分支 |
git branch name | 创建分支 |
git switch name | 切换分支 |
git switch -c name等价于 git cheakout -b name | 创建并切换分支 |
git merge name或 git merge name --no-ff -m “merge with no-ff” | 合并分支 |
conflict | 合并时发生冲突,编辑文件手动解决冲突再提交 |
git branch -d name | 删除分支 |
git log --graph --pretty=oneline --abbrev-commit | 查看分支合并图提交日志 |
bug: git stash, bug分支再commit, git stash pop, git cherry-pick commit版本号 | 隐藏现场,解决bug,恢复现场,复制解决bug代码到当前分支 |
git clone url | 默认会把远程仓库整个给clone下来,但只会在本地默认创建一个master分支 |
git branch --set-upstream-to=remote repository/remote branch local branch | 创建本地分支且指定pull或push的仓库和分支 |
git pull | 拉取远程仓库内容 |
git push | 推送本地仓库内容 |
git remote add 远程仓库起名 url | 关联多个远程仓库 |
git remote --verbose | 详细显示所有远程仓库 |
git remote show name, git remote rm name | 某个远程仓库信息,移除远程仓库 |
tag: git tag v1.0, git tag v1.1 commit 版本号, git tag, git show v1.0, git push origin --tags | 当前提交打标签,某次提交打标签,显示所有标签,标签信息,推送到远程 |
Github: fork, clone, pull request | 远程仓库托管平台 |
二、按以下流程操作:常用命令详细介绍
初始化
- git init 初始化,进行版本控制,任何一个版本库都有主分支master和指向其的指针HEAD
touch 0.md
Linux命令新建文件touch 1.md
进入(tracked)跟踪状态并提交
- git add . 添加到暂存区
git rm --cached file
to ustaged 将暂存区的文件变成未跟踪的状态,保留在工作区
- git commit -m “利用git管理新建的0.md和1.md两个文件” 提交到版本库(主分支master),即此时为最新版本
进行修改:0.md和1.md分别添加内容0md_1、1md_1
git restore file
to discard changes in working directory 将未暂存的文件丢弃更改
- git add . 将所有文件加入暂存区
git restore --staged file
to ustaged 将暂存区的文件返回成未暂存的状态(git restore --staged ./
是对该路径下所有的文件)不提交,对0.md继续修改:添加内容0md_1.1
- git status --short 查看文件状态:0.md既有既有已暂存的部分0md_1,又有未暂存的部分0md_1.1,1.md都在暂存区
- git commit -m “添加内容0md_1、1md_1” commit只提交暂存区的内容
- git diff 查看修改之后还没有暂存起来的变化内容
- git diff --staged 查看已暂存的将要添加到下次提交里的内容
git add 0.md
将未暂存的部分0md_1.1加入暂存区- git commit -m “添加内容0md_1.1” 将暂存区的内容提交
- git commit -a -m “自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过git add步骤”
- git mv 0.md 2.md 版本控制里对文件进行改名
撤销操作
- git commit --amend -m “提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了时,用此命令”。如:由于GitHub提交文件大小的限制,删除在最近未推送的提交了的大文件,git rm --cached giant_file,git commit --amend -CHEAD,git push
- 还有前面的git restore (- -staged) file 撤销(暂存区->未暂存)工作区->未修改
提交历史
- git log (–patch/–pretty=oneline -2) 显示(最近两次-每次提交所引入的差异/每个提交以一行显示)提交历史
- git reset --hard HEAD~3 回退三个版本
- git reset --hard
版本号
回退某个版本- git reflog --pretty=oneline 查看每次的版本改变,因此回退后又可以回来
删除与恢复文件
- 文件管理器删除,或者linux命令删除工作区文件rm file
- git status 会说明哪些文件被删了
- 选择1:
git restore file
to discard changes in working directory,即恢复文件- 选择2:add file 将此删除命令添加到暂存区。接下来用git commit记录此次删除
- 步骤1+4等价于:git rm file ,将工作区和版本库文件删除并将此删除命令添加到暂存区。接下来用git commit记录此删除
- 如何git rm file了还想恢复,只能用git reset --hard
版本号
来将所有文件回退某个版本分支与冲突
- master分支应该是非常稳定,仅用来发布新版本。平时在dev分支上开发新功能,既安全,又不影响别人工作
- 合并分支,只能把commit多的分支往commit少的分支上合并。
- 远程的dev分支在服务器上,除非你登录到服务器,否则开发不了;本地的dev分支在你机器上,直接可以操作,然后和服务器的dev同步;git分支的作用一是同步,二是合并
- 查看分支:git branch
- 创建分支:git branch name
- 切换分支:git checkout name或者git switch name
- 创建分支:创建+切换分支:git checkout -b name或者git switch -c name
- 合并某分支到当前分支:先git switch 当前分支,再git merge 某分支
- git merg dev:合并分支默认是“Fast-forward/快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。但从分支历史上看不出来曾经做过合并。当后面用git branch -d删除分支后,会丢掉分支信息
分支就是一个指针,删除分支就是把那个指针删了,相当于该分支不存在
- git merge --no-ff -m “merge with no-ff” dev:指定普通模式合并分支,在merge时生成一个新的commit,这样从分支历史上就可以看出分支信息。
- 删除分支:git branch -d name。若分支还没有被合并,就会删除失败,。如果是机密文件必需要强行删除,需要使用大写的-D参数,这将导致修改彻底丢失掉。
- 当Git无法自动合并分支时(两个分支修改了同一个文件的同一地方并都进行了提交),就必须首先解决冲突(把Git合并失败的文件手动编辑为我们希望的内容)。解决冲突后,再-m "confict fixed"提交,自动合并完成。
当master分支出现bug时
- 当手头工作dev分支没有完成时,先把工作现场git stash隐藏起来(可以多次stash,用git stash list查看每个工作现场隐藏的位置),然后去修复bug,修复后,再git stash pop恢复工作现场且删除stash内容(等价于:git stash apply stash@{x}恢复指定的stash + git stash drop),继续工作;
- 修复bug:通过创建新的bug分支进行修复提交,然后合并,最后删除;
- 在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick 命令,把bug提交的修改“复制”到当前分支,避免重复劳动。
GitHub远程仓库(一个任务)及多人协作(多台电脑)
- GitHub允许你添加多个Key,这样就可以在每台电脑上往GitHub推送
- 自己一个人维护的小项目,可以只使用一个master分支来实现本地/远程互相交换修改;公司的大项目,可以使用master/dev/release多个分支来实现本地master/远程master、本地dev/远程dev、本地release/远程relase之间交换修改;一切取决于项目管理的需要
- 对于大型项目master分支是主分支(完成的文档),因此要时刻与远程同步。它一般只用来发布最新稳定版本;dev分支是开发分支(多人一起写的文档),团队所有成员都需要在上面工作,所以也需要与远程同步;dev分支完全稳定了才会有一个人将其合并到master分支去发布;bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;feature_n分支用于开发每个新添加的功能,是否推到远程,取决于独立开发(一个人写的文档)还是合作开发(多人一起写的文档)
- 对于大型项目,从远程库clone时默认git branch只能看到master分支。要在dev分支上开发,就必须创建远程origin的dev分支到本地:git branch --set-upstream-to=origin/dev dev
- git clone <github网址> Git给克隆的仓库服务器的默认名字为origin。Git支持多种协议,包括https,但ssh协议速度最快
- git remote add
给远程仓库服务器起名,通常origin
git@server-name:path/repo-name.git 有了本地仓库,关联一个空的远程库,且给远程库起名为origin(如果是多个不同任务的远程仓库,则其不同的名字)
- git remote (-v) 查看已经配置的远程仓库服务器,会显示
远程仓库服务器名,默认origin
(与对应的URL)。如果一个人(一台电脑)多个任务(多个不同任务的远程仓库),就会显示多条信息。- git push -u
远程仓库名,如origin
分支名,如master/dev
用来给某个远程仓库推送某个分支,-u(–set-upstream-to=)用于设置要推送到的位置以及要提取的信息的位置,用于记录push到远端分支的默认值,下次直接用git push默认推送到-u记录的远程仓库和分支- 多人开发的分支在别人push后我再push,或者当本地回退到某个版本后push,会报错。需要先用git pull把最新的提交从origin/dev抓下来,然后在本地合并,解决冲突,(再git rebase把本地未push的分叉提交历史整理成直线)再推送
- git push -f 上述问题报错时使用该命令强制push到远程(不建议)
创建标签
- 在最新的提交打标签: git tag v1.0
- 在历史提交打标签: git tag v1.1 <版本号>
- 查看标签: git tag,默认按字母顺序排列
- 查看标签信息:git show v1.0
- 创建带有说明的标签,用-a指定标签名,-m指定说明文字:git tag -a/–annotate v0.1 -m “version 0.1 released” <版本号>
- 创建的标签都只存储在本地,不会自动推送到远程,若要对远程进行标签操作,如下
- 命令git push origin tagname可以推送一个本地标签;
- 命令git push origin --tags可以推送全部未推送过的本地标签;
- 命令git tag -d tagname可以删除一个本地标签;
- 命令git push origin :refs/tags/tagname 可以删除一个远程标签(要删除远程标签首先要删除本地标签)
Github上的操作
- 在GitHub上,可以任意Fork开源仓库;
- 自己拥有Fork后的仓库的读写权限(从自己的账号下clone仓库,这样才能推送修改);
- 可以推送pull request给官方仓库来贡献代码(对方是否接受pull request就不一定)
三、本地文件夹上传到GitHub(通用)
在git bash中输入:
ssh-keygen -t rsa -C “aifenxxx@163.com”,便生成了.ssh文件夹(公钥密钥对)。把
.ssh文件夹下的id_rsa.pub里面的内容复制到
Github账号的Settings中的SSH and GPS keys的New SSH key里面
- 在Github账号
新建
名为local_file_folder的repository - 在bash中先
cd
到本地文件夹,再
:git init#将本地文件夹纳入版本控制系统 #查看用户名:git config user.name #查看用户邮箱:git config user.email git config --global user.email "aifenxxx@163.com"#配置用户邮箱 git config --global user.name "RX"#配置用户名(以上两步是为了:git log时清楚看到哪个用户提交的信息) #重新配置用户名:git config --global --replace-all user.name "RX" #查看所有配置信息(如用户名、远程仓库等):git config --list git add .#将本地文件夹中的所有文件放入暂存区 git commit -m "first commit local_file_folder"#提交到head区,并记录提交说明 #查看远程仓库:git remote -v #若要更改远程仓库,则先移除原来的远程仓库链接:git remote rm origin git remote add origin git@github.com:xxx/local_file_folder.git#将本地仓库关联Github里新建的名为local_file_folder的空远程仓库,且起名为origin git push -u origin master#名为origin的远程仓库推送master分支
若需要git忽略某个文件夹或文件不上传
:在本地文件夹创建一个.gitignore文件,并将需要忽略上传的文件名写入其中(git-status查看时就没有已忽略的文件了)#.gitignore 中的每一行都排除一个文件或一组(与模式匹配的)文件,如下: #(1) ignore a single file mycode.class #(2) ignore an entire directory /mydebugdir/ #(3) ignore a file type *.json
补充:
若是clone仓库,如何将别人的远程连接改成自己的GitHub远程连接?如何删掉别人的.git文件夹再重新init?(可以在资源管理器-查看-隐藏的项目,删除.git,或在bash中用以下前两条注释掉的命令,再git init)git clone git@github.com:XXX git remote -v#查看目前的远程连接 git remote rm git@github.com:XXX#移除目前的远程连接 #find . -name ".git" | xargs rm -Rf #rm -rf .git #查找并删除.git #git init git add . git commit -m "first commit" git remote add origin git@github.com:YYY#改成自己的GitHub远程连接 git push -u origin master