pages tagged git http://meng6net.localhost/tag/git/ <p><small>Copyright © 2005-2020 by <code>Meng Lu &lt;lumeng3@gmail.com&gt;</code></small></p> Meng Lu's home page ikiwiki Thu, 09 Apr 2020 05:00:48 +0000 git pull from master http://meng6net.localhost/journal/git_pull_from_master/ http://meng6net.localhost/journal/git_pull_from_master/ computing git note Thu, 09 Apr 2020 05:00:48 +0000 2020-04-09T05:00:48Z <ol> <li>Check out your development branch</li> </ol> <pre><code>git checkout my_branch </code></pre> <ol> <li>Update your development branch my pulling commits from origin/master</li> </ol> <p>2a. method 1</p> <pre><code>git pull origin master </code></pre> <p>ab. method 2 ``` git fetch origin master git merge FETCH_HEAD</p> <ol> <li>Resolving conflcits.</li> </ol> <pre><code>git status </code></pre> <p>If it shows some files contain conflicts, manually edit the files and resolve the conflict blocks.</p> <p>git add the files edited. <code>git add my_file_1 ...</code></p> <p>git commit git push</p> <p>(END)</p> Git core.ignoreCase setting http://meng6net.localhost/journal/Git_core.ignoreCase_setting/ http://meng6net.localhost/journal/Git_core.ignoreCase_setting/ Git computing journal note Tue, 16 May 2017 23:59:39 +0000 2017-07-24T04:08:40Z <p>I was reviewing my <code>~/.gitconfig</code> after attending a Git training session in my company. The file was mostly inherited from some source on Internet long time ago, and I hadn't carefully reviewed all the settings there before. I realized that there's an explicit <code>core.ignoreCase</code> setting:</p> <pre><code>[core] ignoreCase = true ... </code></pre> <p>Now I'm not entirely sure if this is a good idea.</p> <p>My observations:</p> <p>On my Mac computer which has the default case-INsensitive file system, no matter if <code>ignoreCase = true</code> or <code>false</code>,</p> <ul> <li><code>git mv myfile myFile</code> does NOT work;</li> <li>'mybranch' and 'myBranch' branches can NOT coexist.</li> </ul> <p>However, on my Linux computer which has case-sensitive file system, no matter if <code>ignoreCase</code> = <code>true</code> or <code>false</code>,</p> <ul> <li><code>git mv myfile myFile</code> works, and <code>git status</code> lists it as a commitable change, and moreover if committed and pushed, it can be checked out and reflected on the Mac computer;</li> <li>'mybranch' and 'myBranch' branches can NOT coexist.</li> </ul> <p>It seems having explicit ignoreCase setting does not make a difference on the same computer, but the behaviors between Mac and Linux differs. From reading the documentation on <code>core.ignoreCase</code> (<a href= "https://git-scm.com/docs/git-config">https://git-scm.com/docs/git-config</a>), I just couldn't decide if keeping <code>ignoreCase = true</code> in my global <code>~/.gitconfig</code> is helpful or harmful.</p> Log statistics for revision control systems http://meng6net.localhost/blog/Log_statistics_for_revision_control_systems/ http://meng6net.localhost/blog/Log_statistics_for_revision_control_systems/ command-line interface computing cvs git mercurial revision control tip unix Tue, 16 May 2017 23:59:39 +0000 2017-05-16T23:59:39Z <h2>Find the top committers to a file</h2> <h3>Mercurial:</h3> <pre> <code>$ hg log ./.hgignore | grep user: | sort | uniq -c | sort -r | head -3 5 user: Michael &lt;michael@foomail.com&gt; 3 user: Mary &lt;mary@barmail.com&gt; </code></pre> <h3>Git:</h3> <pre> <code>$ git log ./.gitignore | grep ^Author: | sort | uniq -c | sort -r | head -3 6 Author: Michael &lt;michael@foomail.com&gt; 2 Author: Mary &lt;mary@foomail.com&gt; </code></pre> <h3>CVS:</h3> <pre> <code>$ cvs log ./foo/bar.cpp | grep author | awk '{print $5}' | sort | uniq -c | sort -r | head -3 92 Michael; 72 Mary; </code></pre> /blog/Log_statistics_for_revision_control_systems/#comments Style Guide for Revision Control System Commit Messages http://meng6net.localhost/blog/Style_Guide_for_Revision_Control_System_Commit_Messages/ http://meng6net.localhost/blog/Style_Guide_for_Revision_Control_System_Commit_Messages/ computing git mercurial revision control style subversion tip Tue, 16 May 2017 23:59:39 +0000 2017-05-16T23:59:39Z <p>Was trying to come up with some style guide for commit messages in revision control systems (Subversion, Git, Mercurial, etc.) as very commonly it is a place where people tend to use poor or poorly-managed writing styles when they are in a hurry, or not. The contrast between the sophistication of engineering of automatic revision control systems and the lousiness of majority of commit messages I've seen is ironic, at least to me. Imagine a situation where one wants to data mine the commit message history in a revision control repository and do text analytics with it to find out some interesting thing about the project, it can be very useful for the commit messages to have a uniform format and hence more machine processable.</p> <h2>Some general rule for revisions and commits</h2> <ul> <li>try to make a commit self-contained, i.e. logically-closely-related revisions should be committed together in one commit rather than in multiple separate commits</li> <li>try to make logically-unrelated revisions in their own separate commits rather than make a big revision including many changes that are logically independent to each other</li> </ul> <h2>Some general rules for having uniform format of the commit messages</h2> <ul> <li> <p>Use a short <em>summary sentence</em> at the top to summarize the main purpose/content of the revision. As both Git and Mercurial use the first sentence ending with <em>period</em> (<code>.</code>) for various purposes. If there are itemized details in the following, use <em>ellipsis</em> (<code>...</code>) instead.</p> </li> <li> <p>Leave a blank line below the <em>summary sentence</em>.</p> </li> <li> <p>Keep the lines shorter than 72 characters as that produces better line wrapping behavior for <code>hg log</code> and <code>git log</code>.</p> </li> <li> <p>If necessary, use bullet items below the blank line to describe details. Use different bullet for different types of revisions</p> <ul> <li> <p><code>+</code> added new content</p> </li> <li> <p><code>-</code> removed existing content</p> </li> <li> <p><code>%</code> modified existing content and/or behavior</p> </li> <li> <p><code>!</code> fixed bugs and errors</p> </li> <li> <p><code>~</code> tweaked content by making small and/or insubstantial changes</p> </li> <li> <p><code>*</code> misc and/or other unclassified changes</p> </li> <li> <p><code>&gt;</code> to-do for future</p> </li> </ul> </li> <li> <p>Try to use expressions with simple past tense or noun phrases.</p> </li> </ul> <p>Example commit message to a revision control repository:</p> <pre><code>Changed the logic dealing with magic input. + added an awesome new functionality - removed obsolete content % modified some existing code ! fixed a bad bug ~ tweaked some content * some misc unclassified changes &gt; make the logic more robust </code></pre> /blog/Style_Guide_for_Revision_Control_System_Commit_Messages/#comments Examples of using myrepos http://meng6net.localhost/computing/example/examples_of_using_myrepos/ http://meng6net.localhost/computing/example/examples_of_using_myrepos/ computing documentation example git myrepos note software tip Tue, 16 May 2017 23:59:39 +0000 2017-05-16T23:59:39Z <h2>Set user name and email to multiple Git repositories</h2> <p>Set up your myrepos and Git repositories according to <a href= "https://myrepos.branchable.com/">https://myrepos.branchable.com/</a>.</p> <p>Add the following in <code>~/.mrconfig</code>:</p> <pre><code>[DEFAULT] ## Teach mr how to config user name and email with `mr configusername` and `mr configuseremail` configusername = git config user.name "Meng Lu" configuseremail = git config user.email lumeng.dev@gmail.com </code></pre> <p>Navigate to a path that contains all the Git repositories you would like to set or update user name and email, and run</p> <pre><code>mr configusername mr configuseremail </code></pre> <p><code>myrepos</code> will print the paths of the Git repositories whose user name and email are updated.</p> <h2>References</h2> <ul> <li><code>myrepos</code>: <a href= "https://myrepos.branchable.com/">https://myrepos.branchable.com/</a>.</li> <li>Git documentation on configuring user: https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup</li> </ul> Examples of using Git http://meng6net.localhost/computing/example/examples_of_using_git/ http://meng6net.localhost/computing/example/examples_of_using_git/ computing documentation example git note software tip Thu, 26 Feb 2015 01:44:09 +0000 2017-07-21T19:47:54Z <h2>Topics</h2> <h3>Run git commands from outside of a Git repository</h3> <pre> <code>git --git-dir=/Users/meng/my-git-repo/.git --work-tree=/Users/meng/my-git-repo/ status </code></pre> <h3>Remove local branches tracking remote branches that no longer present on remotes</h3> <pre><code>git remote prune origin </code></pre> <h3>Generate a list of my commits</h3> <pre> <code>git log --all --no-merges --author='XXX' --stat --after='2015-9-1' | grep -v '^Author: ' </code></pre> <p>Remarks:</p> <ul> <li><code>--all</code> generates the result for all branches;</li> <li><code>--no-merges</code> ignores the merge commits which are often not desirable in a list of additions and revisions one "genuinely authored";</li> <li><code>--author='XXX'</code> restricts the list to commits from a specific author;</li> <li><code>--after='2015-9-1'</code> restricts the list to commits made after the specified date, which is often desirable for listing one's recent commits;</li> <li><code>grep -v '^Author: '</code>: if <code>--author='XXX'</code> is used, the author information for each entry of commit is redundant.</li> </ul> <h3>Find all files committed by a user</h3> <pre> <code>git log --no-merges --stat --author="PATTERN" --name-only --pretty=format:"" | sort -u </code></pre> <p>Remarks:</p> <ul> <li><code>PATTERN</code> is a regex pattern matching the desired user.</li> </ul> <h3>Remove ignored files from index</h3> <h4>Method 1: <code>git update-index --assume-unchanged &lt;file&gt;</code></h4> <p>If a file has been added to the index, i.e. the staging area, but it's decided it does not need to be version controlled by Git, but it should also not be deleted from the working tree, remove it from index:</p> <pre><code>git update-index --assume-unchanged myIgnoredFile </code></pre> <p>This only removes the <code>myIgnoredFile</code> file from the index of the current repository, but will not remove it from the repositories you push to since it only modified the index of the local repository.</p> <p>To add it back later,</p> <pre><code>git update-index --no-assume-unchanged myIgnoredFile </code></pre> <p>List files that are currently assumed unchanged when computing index:</p> <pre> <code>git ls-files -v | grep "^&lt;span class="createlink"&gt;:lower:&lt;/span&gt;" </code></pre> <p>TODO: difference between this method and method 2.</p> <h4>Method 2: <code>git rm --cached &lt;file&gt;</code></h4> <p>If a file has been added to the index, i.e. the staging area, but it's decided it does not need to be version controlled by Git, remove it from index:</p> <pre><code>repo/ $ git rm --cached myIgnoredFile </code></pre> <p>The option <code>--cached</code> limits the removal to the index only and hence the file <code>myIgnoredFile</code> and any modification to it in the working tree is left alone.</p> <h4>Method 3: Method 2 recursively</h4> <p>If there are many files that are added to the index but are then decided to be ignored, and specified by patterns in the <code>.gitignore</code> file, the index can be cleaned as the following</p> <p>Commit changes that's already staged in the index, so files that are already staged but will not need to be ignored later is properly committed:</p> <pre><code>git commit -a -m "XXX" </code></pre> <p>Recursively remove everything from the index</p> <pre><code>git rm -r --cached . </code></pre> <p>Re-add everything, so the modified <code>.gitignore</code> file will ensure the ignored files are not added to the index:</p> <pre><code>git add . </code></pre> <p>Commit:</p> <pre><code>git commit -a -m "XXX" </code></pre> <p>TODO</p> <h3>Always push to multiple remote repositories and pull from one logical central repository</h3> <p>To push to multiple remote repositories automatically everytime you push, but pull only from one remote repository which might be logically considered as the "authoratative" central repository, configure the remote <code>origin</code> as</p> <pre><code>[remote "origin"] url = USER@MYHOST.COM:/PATH//TO/CENTRAL-REPO pushurl = USER@MYHOST.COM:/PATH//TO/CENTRAL-REPO pushurl = git@gitlab.com:XXXuserXXX/BACKUP-REPO1 pushurl = https://XXXuserXXX@bitbucket.org/XXXuserXXX/BACKUP-REPO2.git fetch = +refs/heads/*:refs/remotes/origin/* </code></pre> <p>(The all uppercase parts and the parts sandwiched in between two <code>XXX</code>s should be adjusted to one's real-world values.)</p> <ul> <li> <p><code>git pull</code> or <code>git pull origin master</code> will pull from <code>central-repo</code>;</p> </li> <li> <p><code>git push</code> or <code>git push origin master</code> will push to the logical central repository <code>CENTRAL-REPO</code> as well as the other two backup repositories via the push URLs <code>BACKUP-REPO1</code> and <code>BACKUP-REPO2</code>. But if the <code>pushurl</code> for the <code>CENTRAL-REPO</code> is not explicitly added, it will not be pushed to, i.e. only having <code>url</code> does not suffice. The repositories other than the logical central repository can be used as back-ups or mirrors.</p> </li> </ul> <h3>Rename a branch</h3> <p>Rename a branch:</p> <pre> <code>git branch -m &lt;old_branch_name&gt; &lt;new_branch_name&gt; </code></pre> <p>Or</p> <pre><code>git checkout &lt;old_branch_name&gt; git branch -m &lt;new_branch_name&gt; </code></pre> <p>Remove old branch from the remote <code>origin</code> [<sup id= "fnref:1"><a href="http://meng6net.localhost/tag/git/#fn:1" rel="footnote">1</a></sup>]:</p> <pre><code>git push origin --delete &lt;old_branch_name&gt; </code></pre> <p>or [<sup id="fnref:2"><a href="http://meng6net.localhost/tag/git/#fn:2" rel= "footnote">2</a></sup>]:</p> <pre><code>git push origin :&lt;old_branch_name&gt; </code></pre> <p>Push the new branch to the remote <code>origin</code></p> <pre><code>git push origin -u &lt;new_branch_name&gt; </code></pre> <h2>References</h2> <ul> <li> <p>Sissel, <a href= "http://www.semicomplete.com/blog/geekery/ssl-latency.html">http://www.semicomplete.com/blog/geekery/ssl-latency.html</a></p> </li> <li> <p>Ruan, <a href= "http://www.ruanyifeng.com/blog/2014/09/ssl-latency.html">http://www.ruanyifeng.com/blog/2014/09/ssl-latency.html</a></p> </li> </ul> <div class="footnotes"> <hr /> <ol> <li id="fn:1">git-scm.com, "<em>Deleting Remote Branches</em>," 2016, <a href= "https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches#Deleting-Remote-Branches"> https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches#Deleting-Remote-Branches</a><a href="http://meng6net.localhost/tag/git/#fnref:1" rev="footnote">↩</a></li> <li id="fn:2"><code>&lt;source&gt;:&lt;destination&gt;</code> specifies the refspec to push from and to. When the <code>&lt;source&gt;</code> is omitted, <code>git push origin :&lt;old_branch_name&gt;</code> indicates it pushes an empty refspec to the remote destination branch <code>&lt;old_branch_name&gt;</code> which effectively deletes it on the remote.<a href="http://meng6net.localhost/tag/git/#fnref:2" rev="footnote">↩</a></li> </ol> </div>