<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TortoiseGit &#8211; 编码无悔 /  Intent &amp; Focused</title>
	<atom:link href="https://www.codelast.com/tag/tortoisegit/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.codelast.com</link>
	<description>最优化之路</description>
	<lastBuildDate>Mon, 30 Jan 2023 08:42:37 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>[原创] SVN和Git的一些用法总结</title>
		<link>https://www.codelast.com/%e5%8e%9f%e5%88%9b-linux%e5%91%bd%e4%bb%a4%e8%a1%8c%e4%b8%8b%e4%bd%bf%e7%94%a8svn%e5%92%8cgit%e7%9a%84%e4%b8%80%e4%ba%9b%e7%94%a8%e6%b3%95%e6%80%bb%e7%bb%93/</link>
					<comments>https://www.codelast.com/%e5%8e%9f%e5%88%9b-linux%e5%91%bd%e4%bb%a4%e8%a1%8c%e4%b8%8b%e4%bd%bf%e7%94%a8svn%e5%92%8cgit%e7%9a%84%e4%b8%80%e4%ba%9b%e7%94%a8%e6%b3%95%e6%80%bb%e7%bb%93/#respond</comments>
		
		<dc:creator><![CDATA[learnhard]]></dc:creator>
		<pubDate>Wed, 10 Apr 2013 03:19:53 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[Git命令行]]></category>
		<category><![CDATA[Linux SVN]]></category>
		<category><![CDATA[SVN命令行]]></category>
		<category><![CDATA[TortoiseGit]]></category>
		<category><![CDATA[version control]]></category>
		<category><![CDATA[版本控制]]></category>
		<category><![CDATA[用法]]></category>
		<guid isPermaLink="false">http://www.codelast.com/?p=5719</guid>

					<description><![CDATA[<p>
	&#160;</p>
<p>以下都是比较基础的操作，高手们请绕道，不必浪费时间来看了。</p>
<h3>
	<span style="background-color:#ee82ee;">（A）</span>SVN</h3>
<p><span style="background-color:#00ff00;">➤</span> 查看日志<br />
提交的时候一般会写上注释，如果要查看提交日志，用以下命令：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn log -l 4
</pre>
<p>其中，-l 4表示只查看最近4条日志（也可以没有这样的参数，就表示查看所有日志）。但是你通常会很抓狂地发现，最近的几条日志中，竟然没有你才刚刚提交的那一次的日志！这是怎么回事？日志丢了吗？<br />
其实，是因为你要很用以下命令，更新本地的版本库，才能看到最近提交的日志：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn up
</pre>
<p>这事如果你没注意到，那么可能会浪费你很多时间。问Google也不好找答案，因为这个问题不太好描述，所以不好搜索答案。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&#160;查看指定的版本修改了哪些文件</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn diff --summarize -c 566
</pre>
<p>其中，566是你指定的版本。<br />
<span id="more-5719"></span><br />
<span style="background-color: rgb(0, 255, 0);">➤</span>&#160;查看某个文件在指定的版本修改了什么内容</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn diff Test.java -c 566 &#62; codelast.diff
</pre>
<p>其中，Test.java是你要检查的文件，566是你指定的版本，最后diff被输出到了codelast.diff文件中。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&#160;提交</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn ci -m &#34;Your comment&#34;
</pre>
<p>其中，<span style="color:#0000ff;">Your comment</span> 就是你填写的注释，如果你想换行写，也是可以的，只要你不写后面的那个引号，你可以写一行就回车一次，最后写完了，再加上后面的引号，然后再回车，就执行提交动作了。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&#160;检出指定版本的版本库</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn co https://xxx -r 566
</pre>
<p>其中，https://xxx 是你的版本库地址，566是你要检出的版本号。版本库将被检出到当前路径下。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a>&#8230; <a href="https://www.codelast.com/%e5%8e%9f%e5%88%9b-linux%e5%91%bd%e4%bb%a4%e8%a1%8c%e4%b8%8b%e4%bd%bf%e7%94%a8svn%e5%92%8cgit%e7%9a%84%e4%b8%80%e4%ba%9b%e7%94%a8%e6%b3%95%e6%80%bb%e7%bb%93/" class="read-more">Read More </a></p>]]></description>
										<content:encoded><![CDATA[<p>
	&nbsp;</p>
<p>以下都是比较基础的操作，高手们请绕道，不必浪费时间来看了。</p>
<h3>
	<span style="background-color:#ee82ee;">（A）</span>SVN</h3>
<p><span style="background-color:#00ff00;">➤</span> 查看日志<br />
提交的时候一般会写上注释，如果要查看提交日志，用以下命令：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn log -l 4
</pre>
<p>其中，-l 4表示只查看最近4条日志（也可以没有这样的参数，就表示查看所有日志）。但是你通常会很抓狂地发现，最近的几条日志中，竟然没有你才刚刚提交的那一次的日志！这是怎么回事？日志丢了吗？<br />
其实，是因为你要很用以下命令，更新本地的版本库，才能看到最近提交的日志：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn up
</pre>
<p>这事如果你没注意到，那么可能会浪费你很多时间。问Google也不好找答案，因为这个问题不太好描述，所以不好搜索答案。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;查看指定的版本修改了哪些文件</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn diff --summarize -c 566
</pre>
<p>其中，566是你指定的版本。<br />
<span id="more-5719"></span><br />
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;查看某个文件在指定的版本修改了什么内容</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn diff Test.java -c 566 &gt; codelast.diff
</pre>
<p>其中，Test.java是你要检查的文件，566是你指定的版本，最后diff被输出到了codelast.diff文件中。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;提交</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn ci -m &quot;Your comment&quot;
</pre>
<p>其中，<span style="color:#0000ff;">Your comment</span> 就是你填写的注释，如果你想换行写，也是可以的，只要你不写后面的那个引号，你可以写一行就回车一次，最后写完了，再加上后面的引号，然后再回车，就执行提交动作了。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;检出指定版本的版本库</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn co https://xxx -r 566
</pre>
<p>其中，https://xxx 是你的版本库地址，566是你要检出的版本号。版本库将被检出到当前路径下。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;将指定version的trunk上的代码拷贝到tags的指定目录下</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn cp https://svn.codelast.com/trunk/my-project@1333 https://svn.codelast.com/tags/my-project-r1333
</pre>
<p>如上命令将trunk下的 my-project&nbsp;项目的 1333 版本拷贝到了tags下的 my-project-r1333 中。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;将branches上的指定版本合并（merge）到trunk上<br />
有时候我们会在一个分支（branches）上开发，等开发完成的时候，需要把我们已经提交到branches上的代码合并到trunk上，假设你本地的工作目录是在branches上（刚开发完branches上的一个版本，提交了代码），那么可以像下面这样做：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn switch trunk-url-of-your-project
svn merge branch-url-of-your-project
</pre>
<p>其中，第一条命令是将本地工作目录切换到trunk上。执行完这条命令后，你本地的工作目录里的文件就会变成与trunk里的文件一致。<br />
第二条命令是将branches上的文件合并到本地。执行完这条命令行，你本地的工作目录里的文件就会变成与branches合并的结果。但是请注意，由于本地的工作目录已经是trunk了（用svn info可查看），所以这一更新，就导致本地有若干文件变成&ldquo;已修改，但未提交&rdquo;的状态。因此，你需要把本地因merge被修改过的文件提交一次，就可以使得trunk上的文件变成与branches合并后的版本：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn ci -m &quot;Merge branch to trunk&quot;
</pre>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
关于svn merge的更详细说明，可参考<a href="http://www.subversion.org.cn/svnbook/1.4/svn.ref.svn.c.merge.html" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">此文档</span></a>。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: Ubuntu;">为文件添加上可执行权限</span><br />
假设你有一个脚本文件checkin到代码库中了，但是你在commit之前，却忘了给它添加可执行权限，那么，当checkout出来这份代码时，就会得到一个没有x权限的脚本，还需要手工再为它添加上x权限，非常麻烦。所以，要为该文件添加上x权限：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn propset svn:executable on your-script.sh
</pre>
<p>然后再 svn ci 提交修改即可（尽管你没有修改文件内容，只是修改了文件的权限，也是会被标记为已修改的，需要将此修改提交到代码库中）。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: Ubuntu;">checkout单个文件到本地</span><br />
如果用 <span style="color:#0000ff;">svn checkout 单个文件的URL</span> 来检出一个文件到本地的话，会得到如下的错误提示：</p>
<blockquote>
<p>
		svn: E200007: URL &#39;https://xxx&#39; refers to a file, not a directory</p>
</blockquote>
<p>那么，如何checkout单个文件呢？答案是用<span style="color:#ff0000;">svn export</span>命令即可。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;Review Board提交svn的diff文件时，提示<span style="font-family: 文泉驿等宽微米黑;">&ldquo;</span><span style="color:#0000ff;">The file &#39;https://svn.codelast.com/abc.txt&#39; (r1030) could not be found in the repository</span>&rdquo;错误的解决办法<br />
我遇到的这例错误，是因为我在一个项目中新添加了一个文件abc.txt，于是用 svn add abc.txt 添加它，然后 svn diff &gt; today.diff 生成了项目的diff文件，然后把该diff文件提交到Review Board中，想要生成一个新的review，结果就遇到了上面的错误提示。<br />
这个错误提示乍一看非常搞笑：因为abc.txt是新添加的文件，它当然不会在repository中存在啊！这不是废话么？<br />
同时我注意到，当我执行 svn add abc.txt时，命令行提示：</p>
<blockquote>
<p>
		A &nbsp;(bin) &nbsp;abc.txt</p>
</blockquote>
<p>虽然abc.txt是一个纯文本文件，但是svn貌似把它认作了一个binary文件，于是我Google到了<a href="http://stackoverflow.com/questions/2634043/svn-diff-file-marked-as-binary-type" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">这个链接</span></a>，按照里面的说法，我在 svn add abc.txt 之后进行了如下操作：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
svn propset svn:mime-type &#39;text/plain&#39; abc.txt
</pre>
<p>然后再生成项目的diff文件，再提交到Review Board上，问题搞定！</p>
<h3>
	<span style="background-color:#ee82ee;">（B）</span>Git</h3>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;提交修改到远程的git repository的基本流程（前提是你当前目录已经处于git版本控制之下）<br />
添加当前目录下所有文件到&ldquo;即将提交的列表&rdquo;（当然也可以指定某些指定的文件，将 . 换成指定的文件即可）：</p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git add .
</pre>
<p>将修改提交到本地：</p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git commit -m &quot;对本次修改的注释写在这里&quot;
</pre>
<p>提交到远程的git repository：</p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git push
</pre>
<p>
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">删除远程git repository中的文件<br />
假设要删除当前目录下的abc.txt文件（指远程git repository中的），则：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git rm abc.txt
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">然后提交到本地：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git commit -m &quot;delete a file&quot;
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">然后提交到远程的repository：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git push
</pre>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">TortoiseGit提交代码前弹出错误提示&ldquo;</span>username and email must be set...<span style="font-family: 文泉驿等宽微米黑;">&rdquo;的解决办法<br />
Git Commit（提交）的时候，如果Tortoise弹出一个错误对话框，提示你必须先设置用户名和Email，那么你理所当然地按它的指引点击&ldquo;Yes&rdquo;去设置，奇葩的是，在我的Win7上，TortoiseGit settings&rarr;Git页面中的&ldquo;Name&rdquo;和&ldquo;Email&rdquo;竟然无法输入文字（仿佛输入框是只读的一样）！就算我找到了<a href="http://choorucode.com/2012/12/04/how-to-set-user-name-and-email-in-tortoisegit/" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">这篇</span></a>教程，也无济于事。<br />
后来我又找到了<a href="http://choorucode.com/2012/12/04/how-to-set-user-name-and-email-in-git/" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">这篇</span></a>教程，尝试用命令行去设置，果然OK了：</span></p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
d:\git\bin&gt;git.exe config --global user.name &quot;你的用户名&quot;
d:\git\bin&gt;git.exe config --global user.email &quot;你的Email&quot;
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">执行这两条命令之后，再回到TortoiseGit的settings&rarr;Git页面，就看到Name和Email已经设置好了。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">解决每次 git pull 的时候都提示输入密码的烦人问题<br />
执行以下命令永久保存密码：</span></p>
<blockquote>
<p>
		git config --global credential.helper store</p>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">如果不想永久保存密码，可以在指定的时间内保存密码：</span></p>
<blockquote>
<p>
		git config --global credential.helper &quot;cache --timeout=360000&quot;</p>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">其中，timeout值表示缓存密码多少时间（单位是毫秒还是秒，我不记得了），把它设置为一个非常大的值即可，然后你再git pull的时候，按提示输入密码之后，下一次就不会再提示输入密码了（在timeout时间之内）。</span><br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">Windows下的TortoiseGit每次push的时候都提示要输入密码的问题<br />
可以通过修改TortoiseGit的配置来解决：<br />
在设置界面中，&ldquo;Git&rdquo;设置子项中，点击&ldquo;编辑本地.git/config&rdquo;，会打开一个文本文件，在最后加上如下内容并保存：</span></p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
[credential]
	helper = store
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">然后再push一次并输入密码，TortoiseGit就可以记住你的密码啦。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">提交代码到远程的branch</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git push -u origin local_branch_name:remove_branch_name
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">会把本地的 local_branch_name 这个分支提交到远程的 remote_branch_name 这个分支上，如果远程没有这个分支，就会被创建。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">删除远程的branch</span><br />
<span style="font-family: 文泉驿等宽微米黑;">前面用 git push 命令把本地的分支推送到远程的分支上，命令是很形象的，但是让人非常费解的就是，要删除远程的branch，同样可以用这个push命令：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git push -u origin :remote_branch_name
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">表示删除远程的 remote_branch_name 这个分支。这个让人费解的命令，可以参考<a href="http://git-scm.com/book/zh/v1/Git-%E5%88%86%E6%94%AF-%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">Git手册</span></a>中的说明来理解。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">修改已提交的信息<br />
修改最近一次提交的信息很简单：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git commit --amend
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">在弹出的编辑界面中修改并保存，再用 git log 看一下，提交的信息是不是已经变了？<br />
但如果要编辑的信息，不是最近一次提交呢？这就需要用到 git rebase 命令了。步骤如下：<br />
用 git log 命令查看到你要修改的那一次提交的版本，然后找到比它更旧的再前一个版本的版本号，</span><span style="font-family: 文泉驿等宽微米黑;">例如&nbsp;</span>f0d1fad，然后：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git rebase -i f0d1fad
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">在弹出的编辑界面中，会看到类似于下面的信息：</span></p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
pick a3d4def 修改了一处实现
pick d0ea224 添加了配置文件
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">假设我们要修改的提交信息，是第二行那一次提交，则把它前面的&ldquo;pick&rdquo;改为&ldquo;<span style="color:#0000ff;">edit</span>&rdquo;或&ldquo;<span style="color:#0000ff;">e</span>&rdquo;（就是<span style="color:#0000ff;">edit</span>的缩写），然后保存。<br />
此时，再用 git log 查看一下，最近的一次提交竟然变成了你刚修改的那次提交？没错，然后我们就可以像前面的方法一样，用 git commit --amend 来修改最近一次的提交信息了。<br />
修改完信息之后，还要把 git log 的信息顺序改回来，通过如下命令完成最后一个操作：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git rebase --continue
</pre>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">配置命令别名<br />
例如，git status这个超级常用的命令实在太长了，git st 就很好，可以像下面这样配置，使得执行 git st 的时候，等同于 git status：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git config --global alias.st status
</pre>
<p>
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">查看文件差异<br />
修改了一个文件（该文件已经加入版本控制中了），还没有把它 git add 到暂存区，则用以下命令就可以看到修改了什么：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git diff
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">如果已经把该文件 git add 到了暂存区，再使用 git diff 命令，将没有任何输出。此时，应使用以下两个命令中的任何一个，可以查看到修改的内容（其实显示的就是暂存区里和上一次提前之间的差异）：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git diff --cached
git diff --staged
</pre>
<p>
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">将一个文件移除出版本控制，但是并不将它从本地磁盘上删除<br />
<span style="color:#0000ff;">git rm your_file</span> 会将文件 your_file 从本地以及版本控制系统中都删除掉，但是如果我只想把此文件移除出版本控制系统，但并不想把它从本地磁盘上删除，则可以这样做：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git rm --cached your_file
</pre>
<p>
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;用meld及git-diffall来比较两个版本之间的文件差异<br />
<span style="font-family: 文泉驿等宽微米黑;"><a href="http://meldmerge.org/" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">Meld</span></a>是一款超级强大的图形化diff比较工具，比你用diff命令查看两个文件的差异要直观得多，那么，如何让git与Meld整合到一起呢？需要用到一个叫git-diffall的第三方脚本，下面会说到。</span></p>
<div>
	安装meld：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
sudo apt-get install meld
</pre>
</div>
<div>
	下载git-diffall：<a href="https://github.com/thenigan/git-diffall" rel="noopener noreferrer" target="_blank">https://github.com/thenigan/git-diffall</a></div>
<div>
	解压，把其中的脚本拷贝到 /usr/bin 目录下：</div>
<div>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
sudo cp git-diffall /usr/bin
</pre>
</div>
<div>
	然后配置git的difftool：</div>
<div>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git config --global diff.tool meld
git config --global alias.diffall git-diffall</pre>
</div>
<div>
	现在回到一个项目的目录下，比较一个文件的当前工作版本与master中的版本的差异：</div>
<div>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git difftool ..master src/test/MyClass.java
</pre>
</div>
<div>
	最后一个参数也可以是一个目录，这样就会比较一个目录的差异（太赏心悦目了）。</div>
<div>
	每次执行此命令的时候，都会让用户确认是否加载meld，直接回车即可。</div>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">撤消修改的几种情况<br />
在SVN中，修改了一个文件之后，还没有提交的话，我们可以用 <span style="color:#0000ff;">svn revert your_file</span> 命令，来撤消我们对文件 your_file 所做的修改，使之恢复到没修改之前的状态。但是在Git中，等价的命令是什么呢？在很少使用git之前，我也有这个问题，于是我到Google上一搜&ldquo;</span>svn revert git<span style="font-family: 文泉驿等宽微米黑;">&rdquo;，搜出来很多人都在问这个问题，其实要理解好这个问题，需要先理解好git有工作区、暂存区（stage）的概念，而SVN没有暂存区的概念，所以，当你刚从SVN转到Git时，会很困惑为什么Git撤消修改那么麻烦。其实这才是Git强大之处啊。</span><br />
<span style="font-size: 16px; line-height: 30px;"><span style="background-color:#ffa500;">①</span></span><span style="font-family: 文泉驿等宽微米黑;">修改了一个文件，还没有将它添加到暂存区，此时，要撤消所做的修改：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout -- your_file&nbsp;</pre>
<p><span style="font-size: 16px; line-height: 30px;"><span style="background-color:#ffa500;">②</span></span><span style="font-family: 文泉驿等宽微米黑;">修改了一个文件，并且已经通过 <span style="color:#0000ff;">git add your_file</span> 把它添加到了暂存区，则想把这个文件复原，先要把它从暂存区&ldquo;弄出来&rdquo;：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git reset HEAD your_file
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">现在，你再用 <span style="color:#0000ff;">git status</span> 命令查看的话，会发现它已经被从暂存区&ldquo;拿出来&rdquo;了，变成了没有 git add 的状态，但是，它仍然是我们修改过内容的，要继续撤消我们修改的内容的话，继续像上面一样，用 <span style="color:#0000ff;">git checkout -- your_file</span> 命令，即可将你所做的修改完全复原了。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">查看每个版本修改的文件<br />
<span style="color:#0000ff;">git log</span> 可以查看提交日志，再加一个参数就可以看到每个版本修改的文件都有哪些了：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git log --name-status
</pre>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">一次git add所有modified的文件到暂存区</span><br />
如果你修改了100个文件，那么一个个地 git add 它们到暂存区无异于自虐，此时你需要的是批量add：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git add -i
</pre>
<p>然后就进入了交互式界面：</p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
  1: status	  2: update	  3: revert	  4: add untracked
  5: patch	  6: diff	  7: quit	  8: help
</pre>
<p>选择2，回车，会列出所有将要被 add 的文件，输入星号（*）并回车（表示选择所有文件），然后又会回到上面的菜单界面，选择7回车退出，这时再用 git status 看一下，是不是所有修改过的文件都添加到了暂存区里了？</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">利用Bitbucket在两地同步私有代码</span><br />
<span style="color:#b22222;">(当前，2019.11，GitHub已经可以创建private的repo，写这一条的时候GitHub还不行)</span><br />
与Github不同，Bitbucket可以创建private的代码仓库，这对个人而言非常有用。例如，你在台式机A上写的代码，当你出差到其他城市后，还想在你带的笔记本（记为B）上继续写，那么这时候怎么办？有一个傻傻的办法就是连上电脑A（如果可以的话），然后把整个项目打一个tar包，传到B上，但如果你的整个项目目录非常大，压缩之后仍有几百M，那么你可能需要耗费大量时间来传输。更为可取的一个办法就是利用类似于Bitbucket这样的服务，来同步代码，使得只需要更新少量数据就OK了。<br />
<span style="font-family: 文泉驿等宽微米黑;">下面是步骤：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git remote add origin https://codelast@bitbucket.org/codelast/my-repo.git
</pre>
<div>
	在A处，将代码push到Bitbucket上：</div>
<div>
<pre class="brush:as3;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git push -u origin my-branch:my-branch
</pre>
</div>
<div>
	这表示将my-branch这个branch的代码push到Bitbucket上的同名branch下（如果Bitbucket上没有这个branch，将被创建）。</div>
<div>
	在B处：</div>
<div>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout master
git fetch
</pre>
</div>
<div>
	这会将Bitbucket上的最新修改下载到本地&mdash;&mdash;但是并没有merge到本地的任何一个branch上。</div>
<div>
	在B处，创建同名的branch并切换过去：</div>
<div>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout -b my-branch
git merge origin/my-branch
</pre>
</div>
<div>
	这会将刚才从远程仓库（origin/my-branch）下载回来的最新的代码，merge到当前的branch上，因此，本地的my-branch仓库马上就会变成最新的代码了。</div>
<div>
	看到的提示信息形如：</div>
<div>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
Updating e8b4538..6bc7bcd
Fast-forward
 src/java/com/codelast/Demo.java        |  11 +++++++
 ......
</pre>
</div>
<div>
	至此，B的my-branch这个branch上的代码就与A的代码同步了。</div>
<div>
	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a></div>
<div>
	上面从git fetch开始的步骤，也可以换一种方法实现：</div>
<div>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout -b my-branch
git pull
</pre>
</div>
<div>
	这里的git pull在效果上相当于git fetch ＋ git merge的组合。但是第一次运行这个命令的时候，会看到类似于下面的提示：</div>
<div>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details

    git pull &lt;remote&gt; &lt;branch&gt;

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/&lt;branch&gt; my-branch
</pre>
</div>
<div>
	这说明本地的branch没有和remote的branch关联上，所以git pull不知道&ldquo;从哪里pull&rdquo;。根据最后一次的提示，需要执行以下命令：</div>
<div>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git branch --set-upstream-to=origin/my-branch my-branch
</pre>
</div>
<div>
	会得到提示：</div>
<div>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
Branch my-branch set up to track remote branch my-branch from origin.
</pre>
</div>
<div>
	则现在再执行git pull命令，就可以把remote的branch下载下来并且merge到本地的branch中了。</div>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">查看当前版本比上一个版本修改了什么内容</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git diff HEAD^ HEAD
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">其中，HEAD代表当前版本，后面带一个 ^ 号表示其之前一个版本。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">Git子命令的自动完成／自动补全<br />
在Ubuntu下用 apt-get install git 安装好Git后，Git的子命令就已经能自动完成了，例如你输入 git ad，然后按 TAB，会发现它被补全成了 git add，但是在Arch Linux ARM下，这个功能却没有，我们可以参考<a href="http://code-worrier.com/blog/autocomplete-git/" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">这个</span></a>链接中的教程自己做。</span><br />
基本思想就是获取github上的一个 git-completion.bash 脚本，然后把它添加到开机自动执行的脚本中：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash -o ~/.git-completion.sh
chmod +x ~/.git-completion.sh
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">然后编辑 /etc/profile 文件，在最后添加如下代码：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
if [ -f ~/.git-completion.sh ]; then
    . ~/.git-completion.sh
fi
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">重启系统，搞定，Git已经可以自动完成子命令了。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">检出指定版本的某个文件</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout &lt;commit_id&gt; &lt;your_file_path&gt;
</pre>
<p><span style="font-family: 文泉驿等宽微米黑;">例如：</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout 3493c0ec MyClass.java
</pre>
<p>那么检出的文件放到哪了呢？当然是放到这个文件原来的路径，也就是覆盖了本地的相同文件。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">删除远程已经不存在、本地还存在的远程（remote branch）分支记录<br />
这是什么意思？拿GitLab来举个例子：</span></p>
<ul>
<li>
		<span style="font-family: 文泉驿等宽微米黑;">我在GitLab上提交了一个Merge Request，并且在提交的时候设置了：如果上游接受这个reqeust，则自动删除对应的远程branch</span></li>
<li>
		<span style="font-family: 文泉驿等宽微米黑;">上游接受了这个request，于是我的那个远程branch被GitLab自动删除了</span></li>
<li>
		<span style="font-family: 文泉驿等宽微米黑;">我于是删除了本地的对应branch</span></li>
</ul>
<p><span style="font-family: 文泉驿等宽微米黑;">现在看似和这一次commit相关的清理工作已经做完了，但实际上还没有。用&nbsp;</span><span style="color:#0000ff;">git branch -a</span> 命令，会看到类似于下面的信息：</p>
<blockquote>
<div>
		* master</div>
<div>
		&nbsp; remotes/origin/HEAD -&gt; origin/master</div>
<div>
		<span style="color:#b22222;">&nbsp; remotes/origin/gitlab-test</span></div>
</blockquote>
<div>
	其中，<span style="color:#b22222;">remotes/origin/gitlab-test</span> 就是远程已经删除掉的那个分支的信息，如果你想把这个也清掉，可以用下面的命令：</div>
<blockquote>
<div>
		git remote prune origin</div>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">会打印出一条信息：</span></p>
<blockquote>
<p>
		* [pruned] origin/gitlab-test</p>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">然后再试试 <span style="color:#0000ff;">git branch -a</span>，就会发现那个branch的信息已经删除掉了。</span></p>
<p>
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">fork出来的项目和主干保持同步<br />
假设你在GitLab上fork了一个项目，那么接下来你fork出来的项目就和原项目（称之为主干）无关了，主干更新了代码，你fork出来的项目并不会自动更新代码。<br />
而我们每次开发一个新功能之前，为了防止大量代码冲突，都应该在最新版的代码基础上来开发，因此，让我们fork出来的代码与主干保持一致是有必要的。方法如下：</span></p>
<ul>
<li>
		<span style="font-family: 文泉驿等宽微米黑;">把主干的远程仓库地址添加到你当前项目中</span></li>
</ul>
<blockquote>
<p>
		git remote add upstream git@gitlab.codelast.com:test-repo/test-project.git</p>
</blockquote>
<ul>
<li>
		<span style="font-family: 文泉驿等宽微米黑;">把主干的最新代码检出到本地</span></li>
</ul>
<blockquote>
<p>
		git fetch upstream</p>
</blockquote>
<ul>
<li>
		<span style="font-family: 文泉驿等宽微米黑;">合并主干的最新代码到本地的master分支上（本地的master分支，其对应的远程分支，就是我们前面fork出来的那个项目的master分支）</span></li>
</ul>
<blockquote>
<div>
		git checkout master</div>
<div>
		git merge upstream/master</div>
</blockquote>
<ul>
<li>
		如果merge的时候有冲突(conflict)，那么你需要解决完所有冲突，然后 git add -u 把解决完冲突的文件添加到待commit的区域，然后 git commit 把修改提交到本地</li>
<li>
		<span style="font-family: 文泉驿等宽微米黑;">现在，你本地的master分支已经是比主干更新（或者至少和它一样）的代码了，可以推送到远程你fork出来的那个项目了</span></li>
</ul>
<blockquote>
<p>
		<span style="font-family: 文泉驿等宽微米黑;">git push -u origin master</span></p>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">至此，你fork出来的那个项目，其master分支已经和主干完全同步啦。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">生成指定 commit 的 patch</span></p>
<blockquote>
<p>
		git format-patch -1 {commit-id}</p>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">即会在当前目录下生成一个 .patch 文件。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">设置 commit 信息里的 Email</span></p>
<blockquote>
<p>
		git config user.email abc@gmail.com</p>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">此命令不修改已经提交的commit里的Email，仅对未来的commit生效。</span></p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;使用 git rebase -i 合并本地的多次commit<br />
<span style="font-family: 文泉驿等宽微米黑;">当你在一个branch上开发时，在本地可能会多次提交代码，最后才会push到远程代码服务器上。在本地的多次提交，为了让它们看起来&ldquo;整齐&rdquo;，通常会把它们合并成一个commit再push到远程。合并的过程可以使用 git rebase -i 命令完成。下面就举例说明。<br />
假设你有如下几个commit，从上到下，依次为 时间最新</span>&rarr;<span style="font-family: 文泉驿等宽微米黑;">时间最旧：</span></p>
<blockquote>
<p>
		commit ddddd<br />
		commit ccccc<br />
		commit bbbbb<br />
		commit aaaaa (origin/master, origin/HEAD, master)</p>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">这里面的 commit id 全部都是虚构的（aaaaa～ddddd），只是为了拿来演示。其中，aaaaa这个commit已经push到远程服务器了，它同时也是这四次commit里面时间最老的那个commit。其他几次commit（bbbbb，ccccc，ddddd）全都是在本地的commit，还没有push到远程服务器。为了把这3个本地的commit合并成一个，我们可以执行：</span></p>
<blockquote>
<p>
		<span style="font-family: 文泉驿等宽微米黑;">git rebase -i aaaaa</span></p>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">即：找到所有要合并的commit中，时间最旧的那个commit（即bbbbb）的前一次commit（即aaaaa），再执行 <span style="color:#0000ff;">git rebase -i (找到的commit_id)</span> 命令。<br />
之后Git会自动打开你预先配置好的文本编辑器，进入文本编辑界面：</span></p>
<blockquote>
<div>
		pick ddddd temp</div>
<div>
		pick ccccc temp</div>
<div>
		pick bbbbb temp</div>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">这里面会列出所有待合并的commit的commit_id以及它们的commit message（在这里全都是&quot;temp&quot;，commit的时候随便填的）。我们需要做的是：把时间最新的那个commit（即ddddd）前面的&quot;pick&quot;保持不变，把其他所有commit（即ccccc、bbbbb）前面的&quot;pick&quot;改为&quot;s&quot;，也就是像下面这样：</span></p>
<blockquote>
<div>
		pick ddddd temp</div>
<div>
		s ccccc temp</div>
<div>
		s bbbbb temp</div>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">保存该文件（我配置的Git文本编辑器是VIM，所以在这里用 ESC&nbsp;</span>&rarr; :x<span style="font-family: 文泉驿等宽微米黑;">），马上会进入另一个文本编辑界面：</span></p>
<blockquote>
<div>
		# This is a combination of 3 commits.</div>
<div>
		# This is the 1st commit message:</div>
<div>
		&nbsp;</div>
<div>
		temp</div>
<div>
		&nbsp;</div>
<div>
		# This is the commit message #2:</div>
<div>
		&nbsp;</div>
<div>
		temp</div>
<div>
		&nbsp;</div>
<div>
		# This is the commit message #3:</div>
<div>
		&nbsp;</div>
<div>
		temp<br />
		<span style="color:#a52a2a;">（后面内容很长，全都是#号开头的注释，这里省略）</span></div>
</blockquote>
<div>
	把从第1行开始，到&quot;temp&quot;（含）的所有行全部删除掉，再添加一行新的非注释行，里面写上commit message（即：把3个commit合并成一个以后，这一个commit的message），再保存文件（我用的是VIM，所以这里的操作是 ESC&nbsp;&rarr; :x）。</div>
<p><span style="font-family: 文泉驿等宽微米黑;">此时，合并完成！之后就可以把合并成的那一个commit push到远程服务器上了。</span><br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">git status不显示未追踪的文件（</span>Untracked files）</p>
<blockquote>
<p>
		<span style="font-family: 文泉驿等宽微米黑;">git status -uno</span></p>
</blockquote>
<p><span style="font-family: 文泉驿等宽微米黑;">这里的</span>&quot;-uno&quot;等价于&quot;--untracked-files=no&quot;</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;<span style="font-family: 文泉驿等宽微米黑;">To be added...</span><br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a></p>
<h3>
	<span style="background-color: rgb(238, 130, 238);">（C）</span>git-svn</h3>
<p><a href="http://git-scm.com/book/zh/v1/Git-%E4%B8%8E%E5%85%B6%E4%BB%96%E7%B3%BB%E7%BB%9F-Git-%E4%B8%8E-Subversion" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">git-svn</span></a>是Subversion 双向桥接工具，用于：Git作为本地的版本控制工具，SVN作为远程的仓库。<br />
有人可能会有疑问：为什么会出现git-svn这个东西？这是由于Git实在是比SVN要好用太多太多了，所以有时候，尽管我们不得不使用远程的SVN仓库来和大家同步工作（例如，你公司的代码库就是SVN的），但是在本地，我们仍然可以使用Git来做版本控制，这就是git-svn工具的作用。</p>
<p><span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;初始化<br />
用SVN作为版本控制工具时，我们检出一个项目，用的是 svn co http://xxx 这样的方法，但是用git-svn时，我们应该这样做：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git svn clone http://xxx
</pre>
<p>
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;只查看SVN log<br />
git log 命令会列出你的所有git commit日志，但是如果只想看SVN的commit日志，就需要用：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git svn log
</pre>
<p>但是这样输出的信息可能太杂乱了，可以用如下命令，让一次提交只显示一行信息：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git svn log --oneline
</pre>
<p>
<span style="background-color: rgb(0, 255, 0);">➤</span>&nbsp;本地已经commit了几个版本到git版本库中，但是只想提交一个较旧的版本到远端SVN库中<br />
假设远端repo使用的是SVN，本地使用git-svn来管理，在开发过程中，本地的<span style="color:#ff0000;">my-branch</span>中已经提交了A&rarr;B&rarr;C三个版本，版本A是时间最早的一次提交，版本C是时间最新的一次提交，现在想把版本A上的修改提交到远端SVN repo中，而版本B和版本C暂时不想提交到SVN repo中。但是我们知道，<span style="color:#0000ff;">git-svn dcommit</span>命令会将当前版本的修改全部提交到SVN repo中去，因此，不能在当前版本C中进行此操作，一个可用的方法如下：<br />
切换到工作的branch：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout my-branch
</pre>
<p>在当前branch基础上，再创建一个新的branch，并切换过去：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout -b my-branch-to-commit
</pre>
<p>这时，my-branch-to-commit这个分支上也有版本A、B、C了。假设版本A的commit id为d939ac4，则将此分支的HEAD指向版本A：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git reset --hard d939ac4
</pre>
<p>这时，my-branch-to-commit这个分支上，最新的版本就是版本A了，于是，我们可以把它提交到远端的SVN repo中去了：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git svn dcommit
</pre>
<p>于是我们完成了&ldquo;提交版本A到SVN&rdquo;的任务，但是，我们还要在版本B、版本C的基础上继续开发，所以，下面，我们要把这两个版本&ldquo;找回来&rdquo;。<br />
先切换回master分支：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout master
</pre>
<p>更新到最新的SVN版本：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git svn rebase
</pre>
<p>这时，master分支上已经是版本A的代码了。<br />
再创建一个新的工作分支my-branch-to-continue：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git checkout -b my-branch-to-continue
</pre>
<p>这时，git cherry-pick命令就大显神威了，它可以挑选指定版本的修改，并应用到当前分支上，所以，我们需要做的是，把my-branch这个分支中的版本B、版本C的修改cherry-pick过来，应用到my-branch-to-continue分支上。<br />
假设版本B的commit id为c37d531，版本C的commit id为822dbbd，则：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git cherry-pick c37d531
git cherry-pick 822dbbd
</pre>
<p>这会生成两个新的commit。<br />
现在，在my-branch-to-continue这个分支上，我们的状态就是：版本A已经是提交到了SVN，版本B、版本C已经提交到了本地git repo中。<br />
现在可以把my-branch这个分支删掉了，因为它已经没用了：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
git branch -D my-branch
</pre>
<p>大功告成。</p>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a><br />
<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;版权声明&nbsp;<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;<br />
转载需注明出处：<u><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><em><span style="color: rgb(0, 0, 255);"><strong style="font-size: 16px;"><span style="font-family: arial, helvetica, sans-serif;">codelast.com</span></strong></span></em></a></u>&nbsp;<br />
感谢关注我的微信公众号（微信扫一扫）：</p>
<p style="border: 0px; font-size: 13px; margin: 0px 0px 9px; outline: 0px; padding: 0px; color: rgb(77, 77, 77);">
	<img decoding="async" alt="wechat qrcode of codelast" src="https://www.codelast.com/codelast_wechat_qr_code.jpg" style="width: 200px; height: 200px;" /></p>

			<!--[syntaxhighlighter]-->
			<!--代码高亮，请勿编辑-->
			<script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shCore.js"></script><script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shBrushShell.js"></script>
<script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shBrushPlain.js"></script>
<script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shBrushAS3.js"></script>

			<link type="text/css" rel="stylesheet" href="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/styles/shCoreCk.css" />
			<link type="text/css" rel="stylesheet" href="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/styles/shThemeCk.css" />
			<script type="text/javascript">
			SyntaxHighlighter.defaults['class-name']	= '';
			SyntaxHighlighter.defaults['smart-tabs']	= true;
			SyntaxHighlighter.defaults['tab-size']		= 2;
			SyntaxHighlighter.defaults['gutter']		= true;
			SyntaxHighlighter.defaults['quick-code']	= true;
			SyntaxHighlighter.defaults['collapse'] 		= false;
			SyntaxHighlighter.defaults['auto-links']	= true;
			SyntaxHighlighter.defaults['toolbar']		= true;
			SyntaxHighlighter.all();
			</script>
			<!--[/syntaxhighlighter]-->]]></content:encoded>
					
					<wfw:commentRss>https://www.codelast.com/%e5%8e%9f%e5%88%9b-linux%e5%91%bd%e4%bb%a4%e8%a1%8c%e4%b8%8b%e4%bd%bf%e7%94%a8svn%e5%92%8cgit%e7%9a%84%e4%b8%80%e4%ba%9b%e7%94%a8%e6%b3%95%e6%80%bb%e7%bb%93/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
