-
- 是什么
- 是Linux之父Linus于2002年用C语言开发的分布式版本控制系统。
官方教程中文完整版
关于版本控制系统
类别 | 产品 | 缺点 |
本地版本控制系统VCS Version Control Systems | RCS | 无法协同工作 |
集中式版本控制系统CVCS Centralized Version Control Systems | CVS、Subversion、Perforce | 中央服务器的单点故障 |
分布式版本控制系统DVCS Distributed Version Control System | Git、Mercurial、Bazaar、Darcs |
-
- Git
官方下载地址
Git:Git - Downloads
GitHub Desktop(包含Git):GitHub Desktop | Simple collaboration from your desktop
在Linux上安装Git
Fedora:sudo yum install git
Debian/Ubuntu:sudo apt-get install git。
注:老一点的Debian/Ubuntu,要把命令改为sudo apt-get install git-core,因为以前有个软件也叫GIT(GNU Interactive Tools),结果Git就只能叫git-core了。由于Git名气实在太大,后来就把GNU Interactive Tools改成gnuit,git-core正式改为git。
如果是其他Linux版本,可以直接通过源码安装。先从Git官网下载源码,然后解压,依次输入:./config,make,sudo make install这几个命令安装就好了。
要了解更多选择,Git 官方网站上有在各种 Unix 风格的系统上安装步骤,网址为 Git。
CentOS6.8安装Git2.12
安装依赖包
yum install install autoconf automake libtool -y
yum install zlib zlib-devel -y
yum install perl-devel -y
yum install tcl build-essential tk gettext -y
yum install asciidoc -y
yum install xmlto -y
yum install curl-devel -y
卸载老版本Git
yum remove git
下载源码、解压、编译、安装
wget -c https://github.com/git/git/archive/v2.12.1.tar.gz
tar -zxvf v2.12.1.tar.gz
cd git-2.12.1
make configure
./configure --prefix=/usr/local/git --with-iconv=/usr/local/libiconv
make all doc
sudo make install install-doc install-html
建立软链接(注意:一定要把 /usr/local/git/bin 目录下的所有文件都做个 软连接 !)
ln -s /usr/local/git/bin/git /usr/local/bin/git
ln -s /usr/local/git/bin/git-cvsserver /usr/local/bin/git-cvsserver
ln -s /usr/local/git/bin/gitk /usr/local/bin/gitk
ln -s /usr/local/git/bin/git-receive-pack /usr/local/bin/git-receive-pack
ln -s /usr/local/git/bin/git-shell /usr/local/bin/git-shell
ln -s /usr/local/git/bin/git-upload-archive /usr/local/bin/git-upload-archive
ln -s /usr/local/git/bin/git-upload-pack /usr/local/bin/git-upload-pack
查看是否安装成功
git version
在Mac OS X上安装Git
方法一:是安装homebrew,然后通过homebrew安装Git,具体方法请参考homebrew的文档:Homebrew — The Missing Package Manager for macOS (or Linux)。
方法二(推荐):就是直接从AppStore安装Xcode,Xcode集成了Git,不过默认没有安装,你需要运行Xcode,选择菜单“Xcode”->“Preferences”,在弹出窗口中找到“Downloads”,选择“Command Line Tools”,点“Install”就可以完成安装了。
Xcode是Apple官方IDE,功能非常强大,是开发Mac和iOS App的必选免费装备。
方法三:官网下载安装Git或GitHub Desktop。
在Windows上安装Git
官网下载安装Git或GitHub Desktop
重装Windows后若不想重新安装Git,可直接将Git Bash和Git Gui添加到系统右键菜单(注意修改安装目录):
Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directory\Background\shell\git_bash] @="Git Bash Here" "Icon"="E:\\App\\Git\\mingw64\\share\\git\\git-for-windows.ico" [HKEY_CLASSES_ROOT\Directory\Background\shell\git_bash\command] @="E:\\App\\Git\\git-bash.exe" [HKEY_CLASSES_ROOT\Directory\Background\shell\git_gui] @="GIT GUI here" "Icon"="E:\\App\\Git\\mingw64\\share\\git\\git-for-windows.ico" [HKEY_CLASSES_ROOT\Directory\Background\shell\git_gui\command] @="E:\\App\\Git\\cmd\\git-gui.exe" |
从源代码安装
参考官方教程:1.5 安装 Git
-
- Git
三个配置级别
配置级别 | 配置文件位置(Unix) | 配置文件位置(Windows) | 读写配置变量的git config命令参数 |
系统级别 | /etc/gitconfig | %Git安装目录%/etc/gitconfig | --system |
用户级别 | ~/.gitconfig 或 ~/.config/git/config | %USER_HOME%/.gitconfig | --global |
仓库级别 | $仓库目录/.git/config | %仓库目录%/.git/config |
注:范围小的配置会覆盖范围大的配置
配置用户名和邮件地址
$ git config --global user.name "<Your Name>"
$ git config --global user.email "<email_adress>"(可不用引号标示?)
推荐邮件地址<Your Name>@users.noreply.github.com
配置默认文本编辑器
当 Git 需要你输入信息时会调用它。 如果未配置,Git 会使用操作系统默认的文本编辑器( shell 的环境变量 $EDITOR 所指定的软件),Unix下通常是 Vim。
Unix配置emacs作为Git默认文本编辑器:git config --global core.editor emacs
Windows配置notepad++作为Git默认文本编辑器:
git config --global core.editor "'E:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
配置代码换行符提交检出均不转换
git config --global core.autocrlf false
在Windows下,false为提交检出均不转换;true为提交时转换为LF,检出时转换为CRLF;input为提交时转换为LF,检出时不转换
混合换行符处理
git config --global core.safecrlf 值(true/false/warn)
true:拒绝提交包含混合换行符的文件;false允许提交包含混合换行符的文件;warn提交包含混合换行符的文件时给出警告
让Git Bash显示颜色
git config --global color.ui true
查看配置信息
查看当前系统配置:git config --system --list
查看当前用户配置:git config --global --list
查看当前仓库配置:git config --local --list
查看某项:git config <key>
获取命令用法信息
获取所有:git –help
获取某项:git help <command>或git <command> --help
Git bash终端中文输出显示乱码解决方案
1)终端空白处右键 -> Options... -> Text -> Locale选择zh_CN,Character set选择UTF-8
2)执行命令:git config --global core.quotepath false
------------------------------------------------> | ||||||||
工作目录 Working Directory | 跟踪/暂存修改/ 标记冲突已解决 add | 暂存区 Staging Area | 提交 commit | 版本库 Repository | 推送 push | 远程仓库 Remote/Origin | 拉取请求 pull request | 别人仓库 |
checkout | fetch/clone | fork | ||||||
pull | ||||||||
<-------------------------------------------------- |
使用 Git 时文件的生命周期
版本库又称Git仓库目录,是Git用来保存项目的元数据和对象数据库的地方。这是Git最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。
工作目录是对项目的某个版本独立提取出来的内容。这些从Git仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
暂存区是一个文件,保存了下次将提交的文件列表信息,一般在Git仓库目录中。也称作“索引”。
版本库内有分支、指向第一个分支master的指针HEAD。
内容 | 命令 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
创建版本库(repository) | 目标目录下使用git init命令 注1)Windows系统请确保目录名(包括父目录)不包含中文 注2)创建后目标目录下会生成一个.git隐藏目录 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
把文件添加到版本库 | 三种情况需要将文件添加到版本库: 1)新文件需要纳入版本管理2)已纳入版本管理的文件被修改3)合并代码冲突解决后需要标记已解决 第一步:使用命令git add <file/folder>将工作目录中的文件/目录添加到暂存区,可多次使用,或添加多个文件,添加全部使用git add .。 第二步:使用命令git commit -m "<message>"将暂存区文件提交到分支(未add的文件和修改将不会被提交)。 注: 1)如果git commit 不加-m参数,Git Bash会调用默认的或用户指定的文本编辑器来让用户输入message 2)git commit -v:在编辑器中编辑Git提交消息时能够看到更改的内容 3)git commit -a:跳过暂存区直接将工作区已跟踪文件的修改提交到版本库 4)git commit --amend:该命令可以修改最近一次的commit内容或信息,修改后提交哈希也会改变(类似变基,因此慎重修改已推送的提交) git rebase -i HEAD~2^或HEAD~3:修改最近三次提交信息(慎重修改已推送的提交) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
查看文件状态 | 查看详细的状态报告:git status 查看简洁的状态报告:git status -s或git status –short 简洁的状态报告解释:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
查看修改内容 | 查看工作区相对于暂存区的修改:git diff [<file>] 查看工作区相对于版本库的修改:git diff HEAD -- [<file>] 查看暂存区相对于版本库的修改:git diff --cached [<file>]或git diff --staged [<file>](Git 1.6.1及以上) 注:Git Diff 的插件版本: 可以使用 git difftool 命令来用 Araxis ,emerge 或 vimdiff 等软件输出 diff 分析结果。 使用 git difftool --tool-help 命令来看你的系统支持哪些 Git Diff 插件。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
删除文件 | 对于未跟踪的文件: git clean -n 查看将会删除哪些文件(不会真正删除) Git clean -f 删除当前目录下没有track过的文件 git clean -df 删除当前目录下没有track过的文件和文件夹 或者使用Linux命令rm、rmdir 对于已跟踪未提交的文件: git rm -f <file>:取消跟踪并删除工作区文件(-f参数用来丢弃已修改未提交的内容) 或 git rm --cached <file>:取消跟踪但保留工作区文件 对于已提交的文件: 第一步: git rm [-f] <file>:取消跟踪并删除工作区文件 git rm --cached <file>:取消跟踪但保留工作区文件 第二步:git commit -m "<message>" 也可以先手动删除文件,然后git rm <file>或git add <file>,最后git commit -m "<message>" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
移动/重命名文件 | git mv <file_name> <new_name> 注:运行 git mv README.md README就相当于运行了下面三条命令: $ mv README.md README $ git rm README.md $ git add README | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
查看提交历史 | git log HEAD指向的版本是当前版本。 要退出查看就输入底行命令q 查看按用户分组的提交说明历史,使用命令git shortlog git log常用参数:
| 参数--pretty=format的常用选项:
注:作者指实际修改人,提交者指实际提交人。 示例: 展示简洁的提交历史: git log --pretty=format:"%h - %an, %ad : %s" --date=iso 展示酷炫的提交历史: git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cd) %C(bold blue)<%an>%Creset' --date=iso 筛选指定时间范围的提交历史: git log --since "2019-12-13 22:00:00" --until "2019-12-13 23:16:00" 筛选最近两天内最近两小时外的提交历史: git log --after 2day --before 2hour(单复数随意) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
查看HEAD指针历史 | git reflog HEAD历史包括所有有效和无效的提交历史和重置历史 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
查看所有分支历史 | gitk --all | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
版本回退(重置) | 回到过去: 回退前,可以先查看有效的提交历史,以便确定要回退到哪个版本。 git reset --soft <commit_id>:版本库回退到指定历史 git reset [--mixed] <commit_id>:版本库和暂存区回退到指定历史 git reset --hard <commit_id>:版本库、暂存区和工作区都回退到指定历史 注: 回退到当前版本可用git reset [<参数>] HEAD 或git reset [<参数>] HEAD~0, 回退到上一版本可用git reset [<参数>] HEAD^ 或git reset [<参数>] HEAD~1, 以此类推。 版本回退后,若要推送到远程,需强推:git push -f 回到未来: 先用git reflog查看操作历史,以便确定要回到未来的哪个版本。再用reset命令重返未来。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
版本撤销(反做) | 如果想恢复到之前某个提交的版本,且那个版本之后提交的版本我们都不要了,就用版本回退的方法; 如果要撤销之前某个提交的版本,并且那个版本之后提交的版本我们还要,就用版本撤销的方法。 版本撤销的实质是以新的提交来“反做”某个版本。 版本回退reset会重写提交记录,版本撤销revert不会重写提交记录。 版本撤销容易引起冲突。 git revert -n 要反做的提交哈希 注:-n指不要自动合并 如果要撤销的提交是一个三方合并提交,还需使用-m参数指定使用哪个父提交,值1表示使用进行合并操作的分支上的父提交,值2表示使用合并过来的分支上的父提交。 例如: develop分支提交了一个修改(哈希为1111111) fix分支也提交了一个修改(哈希为2222222) develop分支把fix分支的修改合并进来(三方合并提交,哈希为333333) 后来想要撤销develop合并的fix分支的修改,使用命令: git revert -n 333333 -m 1 版本撤销后,若要推送到远程库,不需强推:git push | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
撤销增/删/改 | 撤销版本库未推送的增/删/改(撤销提交):使用重置版本命令git reset --soft HEAD^ 撤销暂存区未提交的增/删/改(撤销跟踪/暂存):git restore --staged <file>或git reset HEAD <file>(旧) 撤销工作区未暂存的删/改(撤销删除/修改):git restore [--worktree] <file>或git checkout -- <file>(旧) 注:注意git checkout -- <file>与git checkout <branch_name>的区别(后者没有“--”,意为“切换到另一分支”)。 |
文件状态 | 未跟踪 | 已跟踪 | 已修改未暂存 | 已暂存未提交 | 已提交未推送 | 已推送 |
添加文件 | add | commit | push | |||
保存修改 | ||||||
撤销修改 | ||||||
删除文件 | rm | rm -f | ||||
gitignore方式忽略
在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,最后把.gitignore提交到Git,Git就会自动忽略这些文件。
GitHub为我们提供了各种配置文件模板:GitHub - github/gitignore: A collection of useful .gitignore templates,Java的如下:
# Compiled class file *.class # Log file *.log # BlueJ files *.ctxt # Mobile Tools for Java (J2ME) .mtj.tmp/ # Package Files # *.jar *.war *.nar *.ear *.zip *.tar.gz *.rar .idea/ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* | 忽略文件的原则是: 忽略操作系统自动生成的文件,比如缩略图等; 忽略编译生成的中间文件、可执行文件等; 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。 文件 .gitignore 的格式规范如下: 所有空行或者以 # 开头的行都会被 Git 忽略。 可以使用标准的 glob 模式匹配。 匹配模式可以以(/)开头防止递归。 匹配模式可以以(/)结尾指定目录。 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。 所谓的 glob 模式是指 shell 所使用的简化了的正则表达式,例:
|
如果要添加被.gitignore忽略的文件到Git,使用-f参数强制添加,例如:git add -f App.class
查看某文件有没有被.gitignore忽略:git check-ignore -v <file_name>
exclude方式忽略
Git 还提供了另一种 exclude 的方式来做同样的事情,不同的是 .gitignore 这个文件本身会提交到版本库中去。用来保存的是公共的需要排除的文件。而 .git/info/exclude 这里设置的则是你自己本地需要排除的文件。 他不会影响到其他人。也不会提交到版本库中去。
命令行添加exclude文件:git config --global core.excludesfile 文件的绝对路径
已跟踪文件的忽略
忽略跟踪已跟踪文件的改动:git update-index --assume-unchanged 文件路径
恢复跟踪已跟踪文件的改动:git update-index --no-assume-unchanged 文件路径
忽略跟踪已跟踪文件的改动后别人更新远程导致本地拉取报错的解决方法:
报错内容:
error: Your local changes to the following files would be overwritten by merge:
litemall-admin-api/src/main/resources/logback-spring.xml
Please commit your changes or stash them before you merge.
解决方法:
1)恢复跟踪:git update-index --no-assume-unchanged 文件路径
2)储藏本地修改:git stash
3)拉取远程修改:git pull
4)恢复储藏,有冲突解决冲突,解决完不要暂存和提交:git stash pop
注:如果当初忽略跟踪时已暂存,那么上步做完后需把文件回复到最新提交的版本,以保留修改内容:git reset HEAD 文件路径
5)重新忽略跟踪:git update-index --assume-unchanged 文件路径
网上常用的远程仓库
GitHub、gitee
创建并添加SSH Key
为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
最后友情提示,在GitHub上免费托管的Git仓库,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放进去。
如果你不想让别人看到Git库,有两个办法,一个是交点保护费,让GitHub把公开的仓库变成私有的,这样别人就看不见了(不可读更不可写)。另一个办法是自己动手,搭一个Git服务器,因为是你自己的Git服务器,所以别人也是看不见的。这个方法我们后面会讲到的,相当简单,公司内部开发必备。
创建SSH Key
在用户主目录下,看看有没有.ssh目录及目录下有没有id_rsa和id_rsa.pub两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:ssh-keygen -t rsa -C "<email@example.com>",然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
添加SSH Key
登陆GitHub -> 点右上角头像 -> Settings -> SSH and GPG Keys -> New SSH key -> Title自定义,在Key文本框里粘贴id_rsa.pub文件的内容 -> 点“Add SSH Key”-> 完成!
创建远程库
右上角+号 -》New repository -》填入库名例如learngit,其他默认 -》Create repository -》完成!
目前,在GitHub上的这个learngit仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。
克隆远程库
SSH协议克隆(默认):git clone git@<server-name>:<path>/<repo-name>.git [<local-repo-name>]
HTTPS协议克隆:git clone https://<server-name>/<path>/<repo-name>.git [<local-repo-name>]
首先,登陆GitHub,创建一个新的仓库,名字如gitskills,勾选Initialize this repository with a README
然后,在本地执行Git命令:git clone git@github.com:tongwx/gitskills.git或git clone https://github.com/tongwx/gitskills.git
- 克隆的地址可从GitHub仓库的Clone or download按钮中找到。
- 默认配置下Git的克隆操作是首先将远程库的所有文件的所有版本克隆到本地版本库的.git目录下,因此如果服务器挂了,可以使用任一克隆下来的用户端来重建服务器上的仓库(可能会丢失某些服务器端的挂钩设置);其次将最新版本的文件放入工作目录中。
- 使用https协议传输速度慢,每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。
- 当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin。
- 若要克隆时指定远程库名,使用参数-o
- 从远程库clone后,默认只能看到本地的master分支(?),若要创建本地dev分支并关联远程dev分支:git checkout -b dev origin/dev(可取本地分支别名)或者git checkout --track origin/dev(不能取本地分支别名)
- 若要关联本地分支与远程分支:git branch --set-upstream-to=origin/<origin_branch_name> <local_branch_name>或者git branch -u origin/<branch_name>
关联远程库
本地命令:git remote add origin git@<server-name>:<path>/<repo-name>.git
例如:git remote add origin git@github.com:tongwx/learngit.git
查看远程库
查看简略的远程库列表:git remote
查看详细的远程库列表:git remote -v
查看远程库的所有分支:git branch -r
查看本地和远程的所有分支:git branch -a
查看某个远程库信息:git remote show 远程库名
获得远程引用的完整列表:git ls-remote [<remote>]
如果提示fast-forwardable,说明可以推送当前分支。
跟踪远程库
创建远程刚新建分支的本地跟踪分支:git remote update
查看远程已删除分支的本地跟踪分支:git remote prune 远程库名 --dry-run
清除远程已删除分支的本地跟踪分支:git remote prune 远程库名
更新远程分支列表:git remote update --prune或git remote update -p
获取/拉取自远程库
获取/抓取:git fetch 默认只获取远程的默认分支,以及其他分支的指针。
获取/抓取所有:git fetch --all
获取/抓取指定:git fetch <远程主机名> <分支名>
查看刚获取的更新信息:git log -p FETCH_HEAD
合并:git merge <remote>/<branch>
如果在 master 分支时并且它正在跟踪 origin/master 时,可以使用 git merge @{u} 来取代 git merge origin/master。
将拉取下来的最新内容合并到当前所在的分支中:git merge FETCH_HEAD
拉取:git pull,等于git fetch + git merge
完整命令:
名字不一样时:git pull <远程主机名> <远程分支名>:<本地分支名>
名字一样时:git pull <远程主机名> <分支名>
推送到远程库
本地命令:
第一次推送:git push -u 远程库名 本地分支名[:远程分支名]
非第一次推送:git push origin master
注1)Git默认用origin表示远程库。
注2)第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
注3)第一次使用Git的clone或者push命令连接GitHub时,会提示确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可。其后Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了。
如何避免每次输入密码:
如果你正在使用 HTTPS URL 来推送,Git 服务器会询问用户名与密码。 默认情况下它会在终端中提示服务器是否允许你进行推送。
如果不想在每一次推送时都输入用户名与密码,你可以设置一个 “credential cache”。 最简单的方式就是将其保存在内存中几分钟,可以简单地运行 git config --global credential.helper cache 来设置它。
想要了解更多关于不同验证缓存的可用选项,查看 凭证存储。
重命名或移除远程库
重命名远程库:git remote rename 现名 新名
删除远程分支(本地缓存和服务器都删除):git push origin --delete 远程分支名(服务器上会移除指针,保留数据一段时间直到垃圾回收运行删掉数据)
删除本地及远程的分支:git branch -d -r <branchname>
重命名远程分支:先删除远程待修改分支,再push本地新分支到远程服务器
远程库克隆别人的项目
- 在别人项目主页,比如bootstrap项目:GitHub - twbs/bootstrap: The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web. 点“Fork”,就可以克隆别人项目到自己的账户下。
- 从自己的账户下克隆到本地:本地命令:git clone git@github.com:<自己的path>/bootstrap.git
- 如果你希望别人接受你的修改,你就可以在GitHub上发起一个pull request。当然,对方是否接受你的pull request就不一定了。
使用码云
和GitHub相比,码云也提供免费的Git仓库。此外,还集成了代码质量检测、项目演示、私有库等功能。对于团队协作开发,码云还提供了项目管理、代码托管、文档管理的服务,5人以下小团队免费。
码云地址:Gitee - 企业级 DevOps 研发效能平台
上传公钥:登陆码云 -> 点右上角头像 -> 设置 -> SSH公钥 -> 添加公钥 -> 标题自定义,在公钥文本框里粘贴id_rsa.pub文件的内容 -> 点“确定”-> 完成!
创建项目:右上角+号 -》新建仓库 -》填入库名例如learngit,其他默认 -》点“创建” -》完成!
关联本地仓库:例如:git remote add origin git@gitee.com:tongwx/learngit.git
码云同样支持Fork和pull request
一个本地库如何同时关联GitHub和码云
- git remote rm origin
- github):例如:git remote add github git@github.com:tongwx/learngit.git
- gitee):例如:git remote add gitee git@gitee.com:tongwx/learngit.git
- remote -v
- git@gitee.com:tongwx/learngit.git (fetch)
- git@gitee.com:tongwx/learngit.git (push)
- git@github.com:tongwx/learngit.git (fetch)
- git@github.com:tongwx/learngit.git (push)
- GitHub,使用命令:git push github master
- git push gitee master
- fatal: refusing to merge unrelated histories
- --allow-unrelated-histories参数来合并:git push gitee master --allow-unrelated-histories
原理
Git的指针:HEAD -> branch指针 -> commit指针 -> tree指针 -> blob文件快照
Git有个特殊指针叫HEAD,指向本地的当前分支指针。每个分支指针指向各分支的最新提交对象。每个提交对象包含一个指向不同树对象的指针,每个树对象包含指向不同文件快照的指针。
Git会将所有提交串成一条时间线,如果有三方合并提交,时间线将出现分叉。
当Git里只有一条时间线即默认的master分支时,HEAD指针指向分支指针master,master指针指向分支最新的提交。
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。
当我们创建并切换到新的分支例如dev时,Git新建了一个分支指针叫dev,指向与master指针相同指向的提交,再把HEAD指针指向dev指针,就表示当前分支在dev上。
你看,Git创建并切换一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变。
当我们在dev上的工作完成,切换到master并把dev合并到master上时,Git把HEAD指向master指针,把master指针指向dev指针指向的当前提交,就完成了合并。
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支。
命令
查看分支:git branch 注:当前分支前面会标一个*号。
查看分支及指针位置(最新提交点):git branch -v
查看分支及指针位置、正在跟踪哪个远程分支的本地缓存、与本地分支是否是领先、落后或是都有:git branch -vv
一般git branch -vv前先git fetch --all来更新远程分支的本地缓存
创建分支:git branch <name>原理:新建一个指针指向最新提交
切换分支:git checkout <name>或者git switch <name> 注:switch为较新版本命令。原理:HEAD指向目标分支指针
创建+切换分支:git checkout -b <name>或者git switch -c <name> 注:switch为较新版本命令。
在某提交的基础上创建分支:git branch <new_name> 提交哈希
相当于:
1)先使HEAD指针指向某提交(将处于分离头状态detached HEAD state):git checkout 提交哈希,
2)然后创建分支:git branch <new_name>
3)最后使HEAD回到最新提交:git checkout 最新提交哈希
合并/变基分支
合并某分支自与当前分支共同祖先后的提交到当前分支:git merge <name>
合并某分支自与当前分支共同祖先后的提交到当前分支(禁用Fast forward模式):git merge --no-ff -m "<message>" <name>
将当前分支上与基底分支共同祖先后的提交以基底分支最新提交为基底进行重放并前进当前分支:git rebase 基底分支
将变基分支上与基底分支共同祖先后的提交以基底分支最新提交为基底进行重放并前进变基分支:git rebase 基底分支 变基分支
将变基分支上与参照分支共同祖先后的提交以基底分支最新提交为基底进行重放并前进变基分支:git rebase 基底分支 参照分支 变基分支
例如:git rebase --onto master one two
意为:取出在 two分支上自与one分支的共同祖先之后的所有提交,在 master 分支的最新提交快照上重放一遍并创建新的提交,然后把two分支前进至该新提交。
变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。
注意:不要对在你的仓库外有副本的分支执行变基。
只要你把变基命令当作是在推送前整理提交使之整洁的工具,只对从未推送至共用仓库的提交执行变基命令,就不会有事。
如果你或你的同事在某些情形下决意要这么做,请一定要通知每个人执行 git pull --rebase 命令(或者先git fetch,再git rebase 远程库名/远程分支名),这样尽管不能避免伤痛,但能有所缓解。
模式 | 快进合并 | 三方合并 | 变基 |
命令 | git merge <name>(系统自动判断使用快进合并还是三方合并) git merge --no-ff -m "<message>" <name>(强制使用三方合并) | git rebase 目标基底分支 git rebase 目标基底分支 变基分支 git rebase --onto master one two | |
执行结果提示 | Fast-forward | Merge made by the 'recursive' strategy | |
执行前情况 | 当前分支指针所指向的提交是目标分支指针所指向提交的直接上游 (在分支图谱上沿着当前分支前进能到达目标分支) | 当前分支指针所指向的提交不是被合并分支指针所指向提交的直接上游(两个分支出现分叉提交) (在分支图谱上沿着当前分支前进不能到达目标分支) | |
执行过程 | Git直接把当前分支的指针快速前进指向目标分支的指针所指向的提交 | Git使用两个分支的最新提交(快照)和出现分叉前的最近提交(快照)进行三方合并,把合并结果做成一个新的快照并自动创建一个新的提交(合并提交)记录合并的快照,再把当前分支的指针前进指向这个合并提交。 | 将自分叉以来当前分支上的所有提交都以目标基底分支的最新提交快照为基底进行重放,然后把当前分支前进至重放后的最新提交。 |
执行后分支指针情况 | 两个分支指针都指向最新提交 | 目标分支指针落后于当前分支指针,如要保持一致,需切换到目标分支对目标分支进行快进合并 | 基底分支指针落后于当前分支指针,如要保持一致,需切换到基底分支对基地分支进行快进合并。 |
执行后分支图谱情况 | 一条直线,如果删除分支,将丢失历史分支信息 | 可以看到合并前的分叉 | 变基操作的目的是确保在向远程分支推送时保持提交历史的整洁(消除分叉),远程维护者就只需要快进合并即可。 |
合并冲突
如果两个分支对同一个文件的相同部分作出不同修改,将出现合并冲突,合并将暂停,等待解决冲突后手动暂存和提交合并内容。详见冲突管理。
重命名分支
git branch -m <old_name> <new_name>
删除分支
删除已被合并的分支:git branch -d <name>原理:删除该指针
删除未被合并的分支:git branch -D <name>(慎重)原理:删除该指针
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
干活都在dev分支上,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
如果在dev分支上干活的时候发现master分支有bug需要修复,就在master分支上新建fix分支进行修复,然后回到master分支把fix分支的修复合并进master分支,最后回到dev分支上继续干活。
分支开发流程、命令、涉及的分支原理
总体流程
1)上线某个项目,使用一个线上分支master,用来发布新版本,平时不能在上面干活。
2)为实现某个新的需求,创建一个工作分支dev,在该分支上开展工作。
3)完成需求后,切换到master分支,合并dev分支,在master分支发布版本。
如果dev分支的工作尚未完成,突然发现线上分支有个严重问题需要紧急修补,就按如下方式来处理:
1)切换到线上分支。
2)为这个紧急任务新建一个修补分支,并在其中修复它。
3)在测试通过之后,切换回线上分支,然后合并这个修补分支,最后将改动推送到远程线上分支。
4)切换回你最初工作的分支上,把线上分支合并的改动复制到工作分支,然后继续工作。或者先把工作分支的工作做完,再切换到master分支,合并dev分支,在master分支发布版本。
具体流程解析
步骤 | 命令 | 涉及的分支原理 |
使用线上分支master发布项目 | HEAD指向master master指向分支的最新提交 工作目录文件内容与master分支所指向的快照内容一致 | |
为实现某个新的需求,创建并切换到一个工作分支dev | git checkout -b dev | 创建dev指针指向master所指向的提交 HEAD指向dev dev和master分别指向各自分支的最新提交(当前指向同一个提交) 工作目录文件内容无变化,与dev分支所指向的快照内容一致 |
在dev分支上开展工作 | 随着在dev分支上不断提交,dev不断指向该分支的最新提交 fix指向的提交不断领先于master指向的提交 工作目录文件内容不断更新 | |
发现线上分支有问题需紧急修复 | ||
先在当前dev分支把工作现场储藏起来 | git stash | 切换分支前,必须先处理当前分支尚未暂存和提交的修改:要么丢弃修改,要么提交修改,要么储藏修改。否则工作目录的文件内容在切换分支前后会起冲突。 工作目录将未提交的修改移至储藏区 |
切换到master分支 | git checkout master | HEAD指向master master指向的提交落后于dev指向的提交 工作目录文件内容回退到未进行dev开发时的状态 |
从master分支创建并切换到fix分支 | git checkout -b fix | 创建fix指针指向master所指向的提交 HEAD指向fix |
在fix分支上进行修复 | 随着在fix分支上不断提交,fix不断指向该分支的最新提交 fix指向的提交不断领先于master指向的提交 工作目录文件内容不断更新直到fix修复完成 | |
切换回master分支 | git checkout master | HEAD指向master master指向的提交落后于fix指向的提交 工作目录文件内容回退到未进行fix修复时的状态 |
合并fix分支 | git merge [--no-ff -m "<message>"] fix | 快进合并:master快进指向fix所指向的提交(Fast-forward) 三方合并:先自动创建一个合并提交,再把master和fix都指向这个提交 工作目录文件内容更新到fix修复完成后的状态 |
删除fix分支 | git branch -d fix | 删除fix指针 |
切换回dev分支 | git checkout dev | HEAD指向dev 工作目录文件内容变成dev开发时的最后一次提交状态 |
恢复工作现场并删除储藏 | git stash pop (等同于:git stash apply和git stash drop) 可以多次git stash,恢复的时候,先查看储藏列表:git stash list,然后恢复指定的储藏:git stash apply <stash_name> | 工作目录恢复储藏的修改 |
将master分支上的修复复制到dev分支 或者dev分支开发完成后切换到master分支将dev分支并入 | git cherry-pick <commit_id on fix> 或: git commit git checkout master git merge [--no-ff -m "<message>"] dev | 工作目录将master分支上fix修复所做的修改复制进来 或: 工作目录将未提交的修改提交 工作目录变成fix修复完成后的状态 工作目录将dev分支上所有提交的修改合并进来 (由于出现提交分叉,将进行三方合并) |
当合并分支发生冲突时,Git用<<<<<<< 分支名,=======,>>>>>>> 分支名 标记出不同分支的内容。
需要手工修改冲突内容,然后暂存、提交之。
如果想使用图形化工具来解决冲突,可以运行 git mergetool,根据提示选择喜欢的工具来解决冲突。等你退出合并工具之后,Git 会询问刚才的合并是否成功。 如果你回答是,Git 会暂存那些文件以表明冲突已解决。你可以再次运行 git status 来确认所有的合并冲突都已被解决。如果你对结果感到满意,并且确定之前有冲突的的文件都已经暂存了,这时你可以输入 git commit 来完成合并提交。
用带参数的git log --graph可以看到分支合并图:git log --graph --pretty=oneline --abbrev-commit
Git 可以给重要的提交打上标签,是提交的引用。通常在发布一个版本时打一个标签。
打轻量标签:
在最新提交上打标签:git tag <name>
在某个提交上打标签:git tag <name> <commit_id>
打附注标签:可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:git tag -a v0.1 -m "version 0.1 released" 1094adb
查看标签
查看标签列表:git tag
搜索标签:git tag -1 关键字
查看某个标签信息:git show <tagname>
推送标签
推送某个标签到远程:git push <remote> <tagname>
推送全部尚未推送的标签到远程:git push <remote> --tags
删除标签:先删本地:git tag -d <tagname>;再删远程(如有):git push <remote> :refs/tags/<tagname>
检出标签
如果你想查看某个标签所指向的文件版本,可以使用 git checkout <tagname>命令,但这会使你的仓库处于“分离头指针(detacthed HEAD)”状态:在“分离头指针”状态下,如果你做了某些更改然后提交它们,标签不会发生变化,但你的新提交将不属于任何分支,并且将无法访问,除非确切的提交哈希。因此,如果你需要进行更改——比如说你正在修复旧版本的错误——这通常需要创建一个新分支:git checkout -b version2 <tagname>,当然,如果在这之后又进行了一次提交,version2 分支会因为这个改动向前移动,version2 分支就会和<tagname>标签稍微有些不同,这时就应该当心了。
-
- 命令别名
在命令行配置命令别名
git config [--global] alias.<别名> <原命令>
如果要配置别名的原命令中间有空格,需将原命令用引号(单双皆可)标示。
如果要配置外部命令的别名,需在外部命令前加个感叹号。
例:配置一键添加、提交、推送所有修改的命令别名(不知道为啥命令不能用双引号标示):
git config --global alias.go '!git add .; git commit; git push'
在配置文件中配置命令别名
全局配置(当前用户):在用户主目录下的文件.gitconfig(命令行全局配置后会生成)中的[alias]节点中配置,每行一个:别名 = 命令名。
局部配置(当前仓库):在仓库.git目录下的文件config中的[alias]节点中配置,每行一个:别名 = 命令名。
-
- Git服务器
搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装。
假设你已经有sudo权限的用户账号,下面,正式开始安装。
第一步,安装git:
$ sudo apt-get install git
第二步,创建一个git用户,用来运行git服务:
$ sudo adduser git
第三步,创建证书登录:
收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。
第四步,初始化Git仓库:
先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:
$ sudo git init --bare sample.git
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:
$ sudo chown -R git:git sample.git
第五步,禁用shell登录:
出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:
git:x:1001:1001:,,,:/home/git:/bin/bash
改为:
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。
第六步,克隆远程仓库:
现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:
$ git clone git@<server>:/srv/sample.git
剩下的推送就简单了。
要方便管理公钥,用Gitosis。
要像SVN那样控制权限,用Gitolite。
-
- SourceTree
SourceTree是由Atlassian开发的免费Git图形界面工具,可以操作任何Git库。
下载
下载地址:Sourcetree | Free Git GUI for Mac and Windows
SourceTree导入密钥
导入OpenSSH密钥
SourceTree主界面-》工具-》选项-》SSH客户端选择OpenSSH后会自动加载安装Git时创建的id_rsa密钥。
导入PuTTY/Plink密钥
SourceTree主界面-》工具-》创建或导入SSH密钥-》Load-》选择所有文件类型,选择%USER_HOME%\.ssh\id_rsa-》save private key-》保存为%USER_HOME%\.ssh\id_rsa.ppk-》关闭当前界面回到主界面-》工具-》选项-》SSH客户端选择PuTTY/Plink后会自动加载刚创建的id_rsa.ppk密钥。
eclipse 中不同 Git 图标的含义
SVN
软件下载
官方网站:Apache Subversion(点左侧Binary Packages,再点右侧Windows到页尾,有VisualSVN和TortoiseSVN的下载链接)
下载Subversion服务器程序:Download Subversion for Windows
下载VisualSVN Server:Downloads | VisualSVN
下载TortoiseSVN客户端:https://tortoisesvn.net/downloads.html(可以下载语言包Language packs和文档手册Separate manual)
服务器和客户端安装
方式一:安装Subversion服务器和TortoiseSVN客户端
方式二:安装VisualSVN Server和TortoiseSVN客户端
方式三:直接安装1.7以上版本的TortoiseSVN客户端(内含服务端),在组件选择界面要勾选安装命令行工具(command line client tools)。
安装完TortoiseSVN客户端会提示是否重启,若不重启,则图标样式无法生效。可重启explorer.exe进程代替重启系统。
验证安装是否成功:命令:svn --version
Linux下安装服务端:# yum install subversion 安装成功后会显示版本:svnserve, version 1.6.11 (r934486)
创建版本库(Repository)
- 新建版本库目录如:D:\svndemo\repository
- 命令行操作:任意目录运行:svnadmin create D:\svndemo\repository 或者目标目录下运行:svnadmin create .
或者图形化操作:在此目录下右键->TortoiseSVN->Create repository here,然后还可以选择建立文件夹结构。 - 执行上面的命令后,会自动在 repository 下建立多个文件。
启用版本库(SVN服务)
命令行运行:
在任意目录下运行: svnserve -d -r D:\svndemo\repository 或在版本库目录下运行:svnserve -d -r .
默认端口是3390,如果已经有版本库在运行,可以换一个端口运行:svnserve -d -r 版本库路径 --listen-port 3391
如果 D:\svndemo 下还有其他版本库,且要同时启动多个版本库,执行 svnserve -d -r D:\svndemo 即可(多仓库)。
SVN服务器程序就启动了。注意在Windows下不要关闭命令行窗口,否则svnserve停止。
版本库启用后,客户端通过使用以svn://或svn+ssh://为前缀的URL来访问svnserve服务器,实现远程访问SVN版本库。
SVN修改配置文件后可以立即生效,不需要重启服务。
可以使用 svnserve -h 或 svnserve --help 来查看具体的参数(-d后台模式Windows中无效 -r仓库路径)
一般情况下,访问SVN仓库的URL格式形如:svn://192.168.1.6/repoDemo1
但如果启动的是单仓库,则URL直接用:svn://192.168.1.6 表示。svn协议的默认端口号为3690。
把svnserve做为windows服务自动启动:
sc create 服务物理名 binPath= "svnserve.exe的路径 --service -r 仓库目录" Displayname= "在服务中的显示名"
注意所有等号后面要有一空格,安装路径有空格则用\”路径\” 包起来(?)。示例:
sc create svnservice binPath= " C:\Program Files\TortoiseSVN\bin\svnserve.exe --service -r D:\svndemo\repository" DisplayName= "SvnService" depend= Tcpip start= auto
删除该SVN服务:sc delete 服务物理名
配置版本库
进入创建版本库生成的文件夹conf下,进行配置,有以下几个文件:
authz 权限配置文件,该文件名在 svnserve.conf 文件中指定。通过该文件可以实现以路径为基础的访问控制。
passwd 用户和密码本文件。该文件名在 svnserve.conf 文件中指定。
svnserve.conf svn服务配置文件。
这些配置文件保存后就立即生效,不需要重启svnserve服务。
这些配置文件只对svnserve服务有效,即客户端通过前缀为svn://或svn+ssh://的URL访问版本库有效,而对通过前缀http://、https://或file:///的URL无效。
用户配置
修改 passwd 文件,新增用户名和密码(开头不能留空格):
[users] # harry = harryssecret # sally = sallyssecret hello = 123 |
要使 passwd 配置文件生效,需在 svnserve.conf 文件中取消下面这行注释(开头不能留空格):
# password-db = passwd
权限配置
权限配置文件 authz 由一个[groups]配置段和若干个版本库路径权限配置段组成
[groups]配置段中的配置行格式为:用户组 = 用户列表
用户列表由若干个用户组或用户名构成,用户组或用户名之间用逗号","分隔,引用用户组时要使用前缀"@"(如:引用用户组"all"要使用字符串"@all")。
版本库路径权限配置段的段名格式为:[版本库名:路径]
可省略段名中的版本库名。若省略版本库名,则该版本库路径权限段对所有版本库中相同路径的访问控制都有效。如:段名为"[/tmp]"的版本库路径权限段设置了所有引用该权限配置文件的版本库中目录"/tmp"的访问权限。
版本库路径权限配置段中的配置行格式为:用户名或用户组或* = 权限
其中,"*"表示任何用户;权限的取值范围为''、'r'和'rw',''表示对该版本库路径无任何权限,'r'表示有只读权限,'rw'表示有读写权限。
注意:每行配置只能配置单个用户或用户组。
示例:
[groups] g_admin = admin,thinker [admintools:/] @g_admin = rw * = [test:/home/thinker] thinker = rw * = r | 在左例配置文件中,定义了一个用户组"g_admin",该用户组包含用户"admin"和"thinker"。然后定义了2个版本库路径权限段。其中,版本库"admintools"只有用户组"g_admin"可读写,其他用户无任何权限;版本库"test"中路径"/home /thinker"只有用户"thinker"有读写权限,其他用户只有可读权限。 |
要使 anthz 配置文件生效,需在 svnserve.conf 文件中取消下面这行注释(开头不能留空格):
# authz-db = authz
服务配置
修改 svnserve.conf 文件,取消相关行的注释并修改一些值(语句都必须顶格写, 左侧不能留空格, 否则会出错):
[general] anon-access = none # 使非授权用户无法访问(取值范围:read(默认)、write、none) |
注:若两个版本库的认证域相同,建议使用相同的用户名口令数据文件。
初始化导入版本库
方法一:
在要导入的项目的根目录内右键->TortoiseSVN->Import... ->在URL of repository输入“svn://localhost/trunk”(版本库在本机则写localhost,在远程机则写相应地址),在Import Message中输入日志信息->OK->输入用户名密码->OK
方法二:
任意目录右键->TortoiseSVN->Repo-browser->版本库在本地则填svn://localhost/trunk,在远程则改成相应地址->右击trunk->Add folder->选择文件夹->填写注释->OK->输入用户名密码->OK
取出版本库到一个工作副本:来到任意空目录下,在本例中是D:\svndemo\wc1,运行右键->Checkout,在URL of repository中输入svn://localhost/trunk,这样我们就得到了一份工作拷贝。
在工作副本中作出修改并提交:编辑readme.txt文件内容,保存后目录内右键->Commit...,这样我们就把修改提交到了版本库。
查看所作的修改:readme.txt上右键->TortoiseSVN->Show Log,这样我们就可以看到我们对这个文件所有的提交。在版本1上右键->Compare with working copy,我们可以比较工作拷贝的文件和版本1的区别。
SVN命令
SVN Checkout... 将版本库中的内容检出到本地工作副本。
SVN Update 将版本库的修改合并到工作副本中。
SVN Commit... 把工作副本的修改提交到版本库。
Tortoise常见的子命令
Import... 将未纳入版本控制的文件或目录提交到版本库中。
Revert... 将工作副本文件恢复到指定版本。(撤销本地所有未提交的修改,SVN Commit...之后此命令无效)
Add... 将文件或目录纳入版本控制。
SVN使用图标说明
如何仅仅check out 我们想要的一个目录或者文件?
方法一:
1、使用TortiseSVN客户端,右键菜单中的“svn checkout”检出logo.jpg文件的上级目录images文件夹,在检出窗口中的“检出深度”处要选择“仅此项”,这样检出来才是一个空目录,本地命名为temp。
2、然后在temp文件夹上点右键,在弹出的TortiseSVN右键菜单中选择“检查更新”,在“检查更新”窗口中点击“检查版本库”,会列出该“images”目录下的所有文件。
3、在“检查更新”窗口中选中要检出的“logo.jpg”文件,点右键,在右键菜单中选择“更新”,即可将该文件单独检出。
方法二:命令行
1、检出目录images
svn co --depth=empty http://www.iusesvn.com/project1/images
images_work_dir
这样就在本地形成了一个工作拷贝目录images_work_dir
2、进入images_work_dir目录,单独更新logo.jpg
svn up logo.jpg
这样,我们就单独检出了logo.jpg,后面就可以对这个文件进行修改、提交等操作。
如何查看各个版本的差异?
先check out一个文件夹下来到本地(假设这个文件夹的内容好几次被修改了)。在这个文件夹右键单击->TortoiseSVN->ShowLog。出现一个列表,显示所有被修改的文件版本。
右键选中一个版本->Brose repository然后选中一个文件
在最下面的文件筐中右键->show changes
也可以在最上面的筐中右键->compage with previous reversion
如何过滤掉不想提交到svn服务器的文件或者文件夹?
任意目录右键->TortoiseSVN->Settings->General->在Global ignore pattern中填写过滤内容如:*.jpg(这样就不会提交图片了) *.class *.swf *.bat */images/*( 这样就不会提交images目录了)
SVN提交文件时提示文件冲突怎么办?
1. 如果执行svn commit命令时遇到了"xxx is out of date"提示,那么一般是因为您修改了本地某文件或目录结构,而别人也修改了同一个的文件或目录并且先于您提交到了SVN库。
2. 解决的办法是先使用svn update命令获取SVN库上最新修改的文件,这个命令并不会直接覆盖掉您本地所做的修改,SVN客户端会先尝试将SVN库上该文件的修改合并到你的本地文件中。如果SVN客户端成功的进行了合并,您可以再次执行SVNcommit命令进行本地文件的提交即可。
3. 如果SVN客户端无法进行自动合并(可能因为文件是一些二进制文件,或者两人修改的地方是同一个,或者修改的地方太多等原因),则svn客户端会提示“one or more files are in confict state”,即告诉您有文件发生了冲突。
4. 如果是文本文件冲突,则在文件夹下会多出几个冲突文件,如下面列表所示:
f2 这是尝试合并的文件,里面有svn客户端加入的一些标记。 f2.mine 这是本地修改后的文件,即f2.mine是在f2.r69文件基础上更改的。 f2.r69 这是本地修改文件的基础版本(上次更新的版本),69是版本号。 f2.r70 这是服务器上最新版本的文件,即别人修改后提交的文件 |
解决方法:
(1)如果要手工合并修改,则比较f2.r70和f2.mine,将您自己做的修改和别人做的修改手工合并,然后把合并后的内容覆盖到f2中。最后右键点击f2,然后选择 TortoiseSVN -> Resovled... ,之后 f2.mine、f2.r69、f2.r70 文件都会自动被删除。然后您再次执行 SVN Commit 就可以了。
(2)如果要使用工具合并修改,调用TortoiseSVN -> Edit conflicts
(3)如果要保留别人的修改而放弃自己的修改,则可以删掉 f2、f2.mine、f2.r69、f2.r70 几个文件,再执行 SVN Update ,这样会重新从服务器上把最新文件下载到本地。或者执行TortoiseSVN -> Revert...
(4)如果是保留自己的修改而放弃别人的修改,则可以删掉f2、f2.r69、f2.r70 ,留下 f2.mine 并改名为 f2 ,然后执行SVN Commit...,就可以把自己的修改上传到svn服务器。
5. 如果发生冲突的是二进制文件,此时SVN客户端是无法执行自动合并的,这样目录下只会多出以 .rXX 结尾的两个文件,而不会出现 .mine 结尾的文件,此时的处理方法可以参考上面的(2)(3)。
关于冲突的建议
修改文件之前,先进行一次update操作。
修改完成后,及时commit,不要在本地停留过长时间。
在多位团队成员协作时,尽量修改自己撰写的部分,尽量不要修改不属于自己撰写的部分。
出现冲突很正常,可以通过前面的方法解决,不要相互覆盖。
1.在线安装:
(1).点击 Help --> Install New Software...
(2).在弹出的窗口中点击add按钮,Name输入任意名称如subclipse 1.8,Location输入:http://subclipse.tigris.org/update_1.8.x ,点击OK
(3).勾选出现的两个插件,一步步安装即可。
注:目前在线安装svn的版本只有1.6.x和1.8.x,地址分别是:
http://subclipse.tigris.org/update_1.6.x
http://subclipse.tigris.org/update_1.8.x (支持的是Subversion 1.7.x)
2.离线安装:
(1).下载需要的插件包:http://www.oschina.net/p/subclipse/,包里会有"plugins"和"features"两个文件夹
(2).找到eclipse目录下"plugins"和"features"文件夹,将下载好的的svn对应名称文件夹下的内容复制到eclipse的同名文件夹中
(3).通过clean重启Eclipse(方式:打开cmd,进入eclipse安装目录,执行eclipse.exe -clean)
3.link方式:
(1).下载subeclipse插件
(2).创建目录如D:\Plugins\subclipse,将下载好的subclipse压缩包解压在subclipse文件夹中,此时所创建的目录下有features和plugins文件夹及其他文件。
(3).进入eclipse安装目录,创建links文件夹,在文件夹中创建subclipse.link文件
(4).在subclipse.link文件中输入路径地址:path=D:\\Plugins\\subclipse
(5).通过clean重启Eclipse(方式:打开cmd,进入eclipse安装目录,执行eclipse.exe -clean)
注意:
(1).link文件名,插件所在的文件夹名,path路径名,三者必须一致!
(2).如果想暂时不启动插件,只需把link文件删除,或者将path路径改为非插件所在路径即可
-
- 安装 SVN插件
- 插件下载地址:http://subclipse.tigris.org/
- 解压下载好的site-1.10.6.zip文件。
- 在MyEclipse的安装目录下创建myPlugins/svn文件夹,并把从site-1.10.6.zip解压出来的features 和plugins文件夹复制过来。
- 在MyEclipse的安装目录下的dropins文件夹下,新建svn.link文件;文件内容为:path=新创建的myPlugins/svn文件夹的绝对路径
- 重启MyEclipse。
- 在MyEclipse中打开SVN视图:window—show view--other--SVN 资源库
- 在SVN资源库 视图中,右击,点击 新建 — 资源库位置
- 输入资源库URL,例如:svn://192.168.10.1/trunk/itcastTax
- 检出SVN资源库中项目到本地:右击资源库地址,选择 检出为…
- 检出项目后;在本地对应的工作空间将显示该项目。
SVN插件出错问题解决
关于MyEclipse使用Svn 报错问题:(win7 64位 解决示例)
方法一:(无效使用方法二)
Window preference Team SVN 手动修改SVN接口
方法二:
进入如下网站:
http://subclipse.tigris.org/wiki/JavaHL
出现如下页面:
根据系统选择 序号 5 中的内容 点击下载,进入下载页面
点击页面中的 链接 进入如下页面
下载下来是这个文件:Slik-Subversion-1.8.13-x64.msi
双击安装,全部直接默认安装,可以不用跟MyEclipse 同一个目录
重启MyEclipse
设置eclipse作svn同步时忽略某些文件类型和文件夹
window-->preferences-->team-->Ignored Resource-->Add Pattern
SVN日志管理
强制写日志
通过钩子可以实现强制在每次提交的时候写日志:将下面代码存为 pre-commit.bat 文件放到版本库的hooks目录中即可:
@echo off setlocal set REPOS=%1 set TXN=%2 rem check that logmessage contains at least 10 bytes svnlook log "%REPOS%" -t "%TXN%" | findstr ".........." > nul if %errorlevel% gtr 0 goto err exit 0 :err echo Empty log message not allowed. Commit aborted! 提交必须写日志!不得少于10个字节! 1>&2 exit 1 |
可以修改日志但只可修改自己的日志,且不可修改作者
日志写的不好,我们希望修改,默认对Subversion是不允许的,并且会提示需要创建pre-revprop-change钩子。最简单的方式是创建一个空白的pre-revprop-change.bat文件放到版本库的hooks目录下,但是这种方式不够严格,用户具备了修改所有属性的权利,例如修改作者的权利。所以要限制用户只能修改自己的日志且不能修改作者。将下面代码存为 pre-revprop-change.bat 文件放到版本库的hooks目录下即可:
setlocal set REPOS=%1 set REV=%2 set USER=%3 set PROPNAME=%4 set ACTION=%5 rem 不能修改作者,只能修改日志 if not "%ACTION%"=="M" goto refuse if not "%PROPNAME%"=="svn:log" goto refuse rem 只能修改自己的日志 for /f "usebackq" %%k in (`svnlook author %repos% -r %rev%`) do @set var=%%k set rightUser=0 if "%3" == "%superUser%" set rightUser=1 if "%3" == "%var%" set rightUser=1 if %rightUser% == 0 goto ERROR_USER exit 0 :refuse echo Cann't set %PROPNAME%/%ACTION%, only svn:log is allowed! 1>&2 echo 不能修改作者,只能修改日志! 1>&2 endlocal exit 1 :ERROR_USER echo You can only modify your own log! 1>&2 echo 只能修改自己的日志! 1>&2 exit 1 |