CINXE.COM
Git - Debugging with Git
<!DOCTYPE html> <html lang="id"> <head> <meta charset='utf-8'> <meta content='IE=edge,chrome=1' http-equiv='X-UA-Compatible'> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Git - Debugging with Git</title> <link href="/favicon.ico" rel='shortcut icon' type='image/x-icon'> <link rel="stylesheet" href="/application.min.css"> <script src="/js/modernizr.js"></script> <script src="/js/modernize.js"></script> </head> <body id="documentation"> <div class="inner"> <header> <a href="/"><img src="/images/logo@2x.png" width="110" height="46" alt="Git" /></a> <span id="tagline"></span> <script type="text/javascript"> const taglines = [ "fast-version-control", "everything-is-local", "distributed-even-if-your-workflow-isnt", "local-branching-on-the-cheap", "distributed-is-the-new-centralized" ]; var tagline = taglines[Math.floor(Math.random() * taglines.length)]; document.getElementById('tagline').innerHTML = '--' + tagline; </script> <form id="search" action="/search/results"> <input id="search-text" name="search" placeholder="Type / to search entire site…" autocomplete="off" type="text" /> </form> <div id="search-results"></div> </header> </div> <div class="inner"> <div id="content-wrapper"> <div tabindex="1" class="sidebar-btn"></div> <aside class="sidebar" id="sidebar"> <nav> <ul> <li> <a href="/about">About</a> <ul> </ul> </li> <li> <a href="/doc" class="active">Documentation</a> <ul class="expanded"> <li> <a href="/docs">Reference</a> </li> <li> <a href="/book" class="active">Book</a> </li> <li> <a href="/videos">Videos</a> </li> <li> <a href="/doc/ext">External Links</a> </li> </ul> </li> <li> <a href="/downloads">Downloads</a> <ul > <li> <a href="/downloads/guis">GUI Clients</a> </li> <li> <a href="/downloads/logos">Logos</a> </li> </ul> </li> <li> <a href="/community">Community</a> </li> </ul> <hr class="sidebar"> <p> This book is available in <a href="/book/en/v2/Git-Tools-Debugging-with-Git">English</a>. </p> <p> Full translation available in <table> <tr><td><a href="/book/az/v2/Git-Al%c9%99tl%c9%99ri-Git-il%c9%99-Debugging">azərbaycan dili</a>,</td></tr> <tr><td><a href="/book/bg">български език</a>,</td></tr> <tr><td><a href="/book/de/v2/Git-Tools-Debuggen-mit-Git">Deutsch</a>,</td></tr> <tr><td><a href="/book/es/v2/Herramientas-de-Git-Haciendo-debug-con-Git">Español</a>,</td></tr> <tr><td><a href="/book/fr/v2/Utilitaires-Git-D%c3%a9boguer-avec-Git">Français</a>,</td></tr> <tr><td><a href="/book/gr">Ελληνικά</a>,</td></tr> <tr><td><a href="/book/ja/v2/Git-%e3%81%ae%e3%81%95%e3%81%be%e3%81%96%e3%81%be%e3%81%aa%e3%83%84%e3%83%bc%e3%83%ab-Git-%e3%81%ab%e3%82%88%e3%82%8b%e3%83%87%e3%83%90%e3%83%83%e3%82%b0">日本語</a>,</td></tr> <tr><td><a href="/book/ko/v2/Git-%eb%8f%84%ea%b5%ac-Git%ec%9c%bc%eb%a1%9c-%eb%b2%84%ea%b7%b8-%ec%b0%be%ea%b8%b0">한국어</a>,</td></tr> <tr><td><a href="/book/nl/v2/Git-Tools-Debuggen-met-Git">Nederlands</a>,</td></tr> <tr><td><a href="/book/ru/v2/%d0%98%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-Git-%d0%9e%d0%b1%d0%bd%d0%b0%d1%80%d1%83%d0%b6%d0%b5%d0%bd%d0%b8%d0%b5-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba-%d1%81-%d0%bf%d0%be%d0%bc%d0%be%d1%89%d1%8c%d1%8e-Git">Русский</a>,</td></tr> <tr><td><a href="/book/sl/v2/Orodja-Git-Razhro%c5%a1%c4%8devanje-z-Gitom">Slovenščina</a>,</td></tr> <tr><td><a href="/book/tl/v2/Mga-Git-na-Kasangkapan-Pagdebug-gamit-ang-Git">Tagalog</a>,</td></tr> <tr><td><a href="/book/uk/v2/%d0%86%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%b8-Git-%d0%97%d0%bd%d0%b5%d0%b2%d0%b0%d0%b4%d0%b6%d0%b5%d0%bd%d0%bd%d1%8f-%d0%b7-Git">Українська</a></td></tr> <tr><td><a href="/book/zh/v2/Git-%e5%b7%a5%e5%85%b7-%e4%bd%bf%e7%94%a8-Git-%e8%b0%83%e8%af%95">简体中文</a>,</td></tr> </table> </p> <p> Partial translations available in <table> <tr><td><a href="/book/cs/v2/Git-Tools-Lad%c4%9bn%c3%ad-v-syst%c3%a9mu-Git">Čeština</a>,</td></tr> <tr><td><a href="/book/mk/v2/Git-%d0%90%d0%bb%d0%b0%d1%82%d0%ba%d0%b8-%d0%94%d0%b5%d0%b1%d0%b0%d0%b3%d0%b8%d1%80%d0%b0%d1%9a%d0%b5-%d1%81%d0%be-Git">Македонски</a>,</td></tr> <tr><td><a href="/book/pl/v2/Narz%c4%99dzia-Gita-Debugowanie-z-Gitem">Polski</a>,</td></tr> <tr><td><a href="/book/sr/v2/%d0%93%d0%b8%d1%82-%d0%b0%d0%bb%d0%b0%d1%82%d0%b8-%d0%9e%d1%82%d0%ba%d0%bb%d0%b0%d1%9a%d0%b0%d1%9a%d0%b5-%d0%b3%d1%80%d0%b5%d1%88%d0%b0%d0%ba%d0%b0-%d1%81%d0%b0-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%be%d0%bc-Git">Српски</a>,</td></tr> <tr><td><a href="/book/uz/v2/Git-Tools-Debugging-with-Git">Ўзбекча</a>,</td></tr> <tr><td><a href="/book/zh-tw/v2/Git-%e5%b7%a5%e5%85%b7-Debugging-with-Git">繁體中文</a>,</td></tr> </table> </p> <p> Translations started for <table> <tr><td><a href="/book/be/v2/Git-Tools-Debugging-with-Git">Беларуская</a>,</td></tr> <tr><td><a href="/book/fa/v2/Git-Tools-Debugging-with-Git" dir="rtl">فارسی</a>,</td></tr> <tr><td><a href="/book/id/v2/Git-Tools-Debugging-with-Git">Indonesian</a>,</td></tr> <tr><td><a href="/book/it/v2/Git-Tools-Debugging-with-Git">Italiano</a>,</td></tr> <tr><td><a href="/book/ms/v2/Git-Tools-Debugging-with-Git">Bahasa Melayu</a>,</td></tr> <tr><td><a href="/book/pt-br/v2/Git-Tools-Debugging-with-Git">Português (Brasil)</a>,</td></tr> <tr><td><a href="/book/pt-pt/v2/Ferramentas-do-Git-Debugging-with-Git">Português (Portugal)</a>,</td></tr> <tr><td><a href="/book/sv/v2/Git-Tools-Debugging-with-Git">Svenska</a>,</td></tr> <tr><td><a href="/book/tr/v2/Git-Ara%c3%a7lar%c4%b1-Git%e2%80%99le-Hata-Ay%c4%b1klama">Türkçe</a>.</td></tr> </table> </p> <hr class="sidebar"/> <p> The source of this book is <a href="https://github.com/progit/progit2-id">hosted on GitHub.</a></br> Patches, suggestions and comments are welcome. </p> </nav> </aside> <div id="content"> <div id="book-chapters"> <a class="dropdown-trigger" id="book-chapters-trigger" data-panel-id="chapters-dropdown" href="#">Chapters ▾</a> <div class='dropdown-panel' id='chapters-dropdown'> <div class='three-column'> <div class="column-left"> <ol class='book-toc'> <li class='chapter'> <h2>1. <a href="/book/id/v2/Memulai-Tentang-Version-Control">Memulai</a></h2> <ol> <li> 1.1 <a href="/book/id/v2/Memulai-Tentang-Version-Control">Tentang Version Control</a> </li> <li> 1.2 <a href="/book/id/v2/Memulai-Sejarah-Singkat-Git">Sejarah Singkat Git</a> </li> <li> 1.3 <a href="/book/id/v2/Memulai-Dasar-dasar-Git">Dasar-dasar Git</a> </li> <li> 1.4 <a href="/book/id/v2/Memulai-Command-Line">Command Line</a> </li> <li> 1.5 <a href="/book/id/v2/Memulai-Memasang-Git">Memasang Git</a> </li> <li> 1.6 <a href="/book/id/v2/Memulai-Pengaturan-Awal-Git">Pengaturan Awal Git</a> </li> <li> 1.7 <a href="/book/id/v2/Memulai-Mendapatkan-Bantuan">Mendapatkan Bantuan</a> </li> <li> 1.8 <a href="/book/id/v2/Memulai-Kesimpulan">Kesimpulan</a> </li> </ol> </li> <li class='chapter'> <h2>2. <a href="/book/id/v2/Git-Basics-Mendapatkan-Repository-Git">Git Basics</a></h2> <ol> <li> 2.1 <a href="/book/id/v2/Git-Basics-Mendapatkan-Repository-Git">Mendapatkan Repository Git</a> </li> <li> 2.2 <a href="/book/id/v2/Git-Basics-Recording-Changes-to-the-Repository">Recording Changes to the Repository</a> </li> <li> 2.3 <a href="/book/id/v2/Git-Basics-Viewing-the-Commit-History">Viewing the Commit History</a> </li> <li> 2.4 <a href="/book/id/v2/Git-Basics-Undoing-Things">Undoing Things</a> </li> <li> 2.5 <a href="/book/id/v2/Git-Basics-Working-with-Remotes">Working with Remotes</a> </li> <li> 2.6 <a href="/book/id/v2/Git-Basics-Tagging">Tagging</a> </li> <li> 2.7 <a href="/book/id/v2/Git-Basics-Alias-Git">Alias Git</a> </li> <li> 2.8 <a href="/book/id/v2/Git-Basics-Summary">Summary</a> </li> </ol> </li> <li class='chapter'> <h2>3. <a href="/book/id/v2/Git-Branching-Branches-in-a-Nutshell">Git Branching</a></h2> <ol> <li> 3.1 <a href="/book/id/v2/Git-Branching-Branches-in-a-Nutshell">Branches in a Nutshell</a> </li> <li> 3.2 <a href="/book/id/v2/Git-Branching-Basic-Branching-and-Merging">Basic Branching and Merging</a> </li> <li> 3.3 <a href="/book/id/v2/Git-Branching-Branch-Management">Branch Management</a> </li> <li> 3.4 <a href="/book/id/v2/Git-Branching-Branching-Workflows">Branching Workflows</a> </li> <li> 3.5 <a href="/book/id/v2/Git-Branching-Remote-Branches">Remote Branches</a> </li> <li> 3.6 <a href="/book/id/v2/Git-Branching-Rebasing">Rebasing</a> </li> <li> 3.7 <a href="/book/id/v2/Git-Branching-Summary">Summary</a> </li> </ol> </li> <li class='chapter'> <h2>4. <a href="/book/id/v2/Git-di-Server-Protokol">Git di Server</a></h2> <ol> <li> 4.1 <a href="/book/id/v2/Git-di-Server-Protokol">Protokol</a> </li> <li> 4.2 <a href="/book/id/v2/Git-di-Server-Getting-Git-on-a-Server">Getting Git on a Server</a> </li> <li> 4.3 <a href="/book/id/v2/Git-di-Server-Generating-Your-SSH-Public-Key">Generating Your SSH Public Key</a> </li> <li> 4.4 <a href="/book/id/v2/Git-di-Server-Setting-Up-the-Server">Setting Up the Server</a> </li> <li> 4.5 <a href="/book/id/v2/Git-di-Server-Git-Daemon">Git Daemon</a> </li> <li> 4.6 <a href="/book/id/v2/Git-di-Server-Smart-HTTP">Smart HTTP</a> </li> <li> 4.7 <a href="/book/id/v2/Git-di-Server-GitWeb">GitWeb</a> </li> <li> 4.8 <a href="/book/id/v2/Git-di-Server-GitLab">GitLab</a> </li> <li> 4.9 <a href="/book/id/v2/Git-di-Server-Third-Party-Hosted-Options">Third Party Hosted Options</a> </li> <li> 4.10 <a href="/book/id/v2/Git-di-Server-Ringkasan">Ringkasan</a> </li> </ol> </li> <li class='chapter'> <h2>5. <a href="/book/id/v2/Distributed-Git-Distributed-Workflows">Distributed Git</a></h2> <ol> <li> 5.1 <a href="/book/id/v2/Distributed-Git-Distributed-Workflows">Distributed Workflows</a> </li> <li> 5.2 <a href="/book/id/v2/Distributed-Git-Contributing-to-a-Project">Contributing to a Project</a> </li> <li> 5.3 <a href="/book/id/v2/Distributed-Git-Maintaining-a-Project">Maintaining a Project</a> </li> <li> 5.4 <a href="/book/id/v2/Distributed-Git-Summary">Summary</a> </li> </ol> </li> </ol> </div> <div class='column-middle'> <ol class='book-toc'> <li class='chapter'> <h2>6. <a href="/book/id/v2/GitHub-Pengaturan-dan-Konfigurasi-Akun">GitHub</a></h2> <ol> <li> 6.1 <a href="/book/id/v2/GitHub-Pengaturan-dan-Konfigurasi-Akun">Pengaturan dan Konfigurasi Akun</a> </li> <li> 6.2 <a href="/book/id/v2/GitHub-Contributing-to-a-Project">Contributing to a Project</a> </li> <li> 6.3 <a href="/book/id/v2/GitHub-Maintaining-a-Project">Maintaining a Project</a> </li> <li> 6.4 <a href="/book/id/v2/GitHub-Mengelola-Organization">Mengelola Organization</a> </li> <li> 6.5 <a href="/book/id/v2/GitHub-Scripting-GitHub">Scripting GitHub</a> </li> <li> 6.6 <a href="/book/id/v2/GitHub-Ringkasan">Ringkasan</a> </li> </ol> </li> <li class='chapter'> <h2>7. <a href="/book/id/v2/Git-Tools-Revision-Selection">Git Tools</a></h2> <ol> <li> 7.1 <a href="/book/id/v2/Git-Tools-Revision-Selection">Revision Selection</a> </li> <li> 7.2 <a href="/book/id/v2/Git-Tools-Interactive-Staging">Interactive Staging</a> </li> <li> 7.3 <a href="/book/id/v2/Git-Tools-Stashing-and-Cleaning">Stashing and Cleaning</a> </li> <li> 7.4 <a href="/book/id/v2/Git-Tools-Signing-Your-Work">Signing Your Work</a> </li> <li> 7.5 <a href="/book/id/v2/Git-Tools-Searching">Searching</a> </li> <li> 7.6 <a href="/book/id/v2/Git-Tools-Rewriting-History">Rewriting History</a> </li> <li> 7.7 <a href="/book/id/v2/Git-Tools-Reset-Demystified">Reset Demystified</a> </li> <li> 7.8 <a href="/book/id/v2/Git-Tools-Advanced-Merging">Advanced Merging</a> </li> <li> 7.9 <a href="/book/id/v2/Git-Tools-Rerere">Rerere</a> </li> <li> 7.10 <a href="/book/id/v2/Git-Tools-Debugging-with-Git" class="active">Debugging with Git</a> </li> <li> 7.11 <a href="/book/id/v2/Git-Tools-Submodules">Submodules</a> </li> <li> 7.12 <a href="/book/id/v2/Git-Tools-Bundling">Bundling</a> </li> <li> 7.13 <a href="/book/id/v2/Git-Tools-Replace">Replace</a> </li> <li> 7.14 <a href="/book/id/v2/Git-Tools-Credential-Storage">Credential Storage</a> </li> <li> 7.15 <a href="/book/id/v2/Git-Tools-Summary">Summary</a> </li> </ol> </li> <li class='chapter'> <h2>8. <a href="/book/id/v2/Kostumisasi-Git-Konfigurasi-Git">Kostumisasi Git</a></h2> <ol> <li> 8.1 <a href="/book/id/v2/Kostumisasi-Git-Konfigurasi-Git">Konfigurasi Git</a> </li> <li> 8.2 <a href="/book/id/v2/Kostumisasi-Git-Git-Attributes">Git Attributes</a> </li> <li> 8.3 <a href="/book/id/v2/Kostumisasi-Git-Git-Hooks">Git Hooks</a> </li> <li> 8.4 <a href="/book/id/v2/Kostumisasi-Git-An-Example-Git-Enforced-Policy">An Example Git-Enforced Policy</a> </li> <li> 8.5 <a href="/book/id/v2/Kostumisasi-Git-Ringkasan">Ringkasan</a> </li> </ol> </li> <li class='chapter'> <h2>9. <a href="/book/id/v2/Git-and-Other-Systems-Git-as-a-Client">Git and Other Systems</a></h2> <ol> <li> 9.1 <a href="/book/id/v2/Git-and-Other-Systems-Git-as-a-Client">Git as a Client</a> </li> <li> 9.2 <a href="/book/id/v2/Git-and-Other-Systems-Migrating-to-Git">Migrating to Git</a> </li> <li> 9.3 <a href="/book/id/v2/Git-and-Other-Systems-Summary">Summary</a> </li> </ol> </li> <li class='chapter'> <h2>10. <a href="/book/id/v2/Git-Internals-Plumbing-and-Porcelain">Git Internals</a></h2> <ol> <li> 10.1 <a href="/book/id/v2/Git-Internals-Plumbing-and-Porcelain">Plumbing and Porcelain</a> </li> <li> 10.2 <a href="/book/id/v2/Git-Internals-Git-Objects">Git Objects</a> </li> <li> 10.3 <a href="/book/id/v2/Git-Internals-Git-References">Git References</a> </li> <li> 10.4 <a href="/book/id/v2/Git-Internals-Packfiles">Packfiles</a> </li> <li> 10.5 <a href="/book/id/v2/Git-Internals-The-Refspec">The Refspec</a> </li> <li> 10.6 <a href="/book/id/v2/Git-Internals-Transfer-Protocols">Transfer Protocols</a> </li> <li> 10.7 <a href="/book/id/v2/Git-Internals-Maintenance-and-Data-Recovery">Maintenance and Data Recovery</a> </li> <li> 10.8 <a href="/book/id/v2/Git-Internals-Environment-Variables">Environment Variables</a> </li> <li> 10.9 <a href="/book/id/v2/Git-Internals-Summary">Summary</a> </li> </ol> </li> </ol> </div> <div class='column-right'> <ol class='book-toc'> <li class='chapter'> <h2>A1. <a href="/book/id/v2/Appendix-A:-Git-in-Other-Environments-Graphical-Interfaces">Appendix A: Git in Other Environments</a></h2> <ol> <li> A1.1 <a href="/book/id/v2/Appendix-A:-Git-in-Other-Environments-Graphical-Interfaces">Graphical Interfaces</a> </li> <li> A1.2 <a href="/book/id/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Visual-Studio">Git in Visual Studio</a> </li> <li> A1.3 <a href="/book/id/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Eclipse">Git in Eclipse</a> </li> <li> A1.4 <a href="/book/id/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Bash">Git in Bash</a> </li> <li> A1.5 <a href="/book/id/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Zsh">Git in Zsh</a> </li> <li> A1.6 <a href="/book/id/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Powershell">Git in Powershell</a> </li> <li> A1.7 <a href="/book/id/v2/Appendix-A:-Git-in-Other-Environments-Summary">Summary</a> </li> </ol> </li> <li class='chapter'> <h2>A2. <a href="/book/id/v2/Appendix-B:-Embedding-Git-in-your-Applications-Command-line-Git">Appendix B: Embedding Git in your Applications</a></h2> <ol> <li> A2.1 <a href="/book/id/v2/Appendix-B:-Embedding-Git-in-your-Applications-Command-line-Git">Command-line Git</a> </li> <li> A2.2 <a href="/book/id/v2/Appendix-B:-Embedding-Git-in-your-Applications-Libgit2">Libgit2</a> </li> <li> A2.3 <a href="/book/id/v2/Appendix-B:-Embedding-Git-in-your-Applications-JGit">JGit</a> </li> </ol> </li> <li class='chapter'> <h2>A3. <a href="/book/id/v2/Appendix-C:-Git-Commands-Setup-and-Config">Appendix C: Git Commands</a></h2> <ol> <li> A3.1 <a href="/book/id/v2/Appendix-C:-Git-Commands-Setup-and-Config">Setup and Config</a> </li> <li> A3.2 <a href="/book/id/v2/Appendix-C:-Git-Commands-Getting-and-Creating-Projects">Getting and Creating Projects</a> </li> <li> A3.3 <a href="/book/id/v2/Appendix-C:-Git-Commands-Basic-Snapshotting">Basic Snapshotting</a> </li> <li> A3.4 <a href="/book/id/v2/Appendix-C:-Git-Commands-Branching-and-Merging">Branching and Merging</a> </li> <li> A3.5 <a href="/book/id/v2/Appendix-C:-Git-Commands-Sharing-and-Updating-Projects">Sharing and Updating Projects</a> </li> <li> A3.6 <a href="/book/id/v2/Appendix-C:-Git-Commands-Inspection-and-Comparison">Inspection and Comparison</a> </li> <li> A3.7 <a href="/book/id/v2/Appendix-C:-Git-Commands-Debugging">Debugging</a> </li> <li> A3.8 <a href="/book/id/v2/Appendix-C:-Git-Commands-Patching">Patching</a> </li> <li> A3.9 <a href="/book/id/v2/Appendix-C:-Git-Commands-Email">Email</a> </li> <li> A3.10 <a href="/book/id/v2/Appendix-C:-Git-Commands-External-Systems">External Systems</a> </li> <li> A3.11 <a href="/book/id/v2/Appendix-C:-Git-Commands-Administration">Administration</a> </li> <li> A3.12 <a href="/book/id/v2/Appendix-C:-Git-Commands-Plumbing-Commands">Plumbing Commands</a> </li> </ol> </li> </ol> </div> </div> </div> <span class="light" id="edition"> 2nd Edition </span> </div> <div id="main" data-pagefind-filter="category:book" data-pagefind-meta="category:Book" data-pagefind-weight="0.05" data-pagefind-body class="book edition2"> <h1>7.10 Git Tools - Debugging with Git</h1> <div> <h2 id="_debugging_with_git">Debugging with Git</h2> <div class="paragraph"> <p>Git also provides a couple of tools to help you debug issues in your projects. Because Git is designed to work with nearly any type of project, these tools are pretty generic, but they can often help you hunt for a bug or culprit when things go wrong.</p> </div> <div class="sect3"> <h3 id="_file_annotation">File Annotation</h3> <div class="paragraph"> <p>If you track down a bug in your code and want to know when it was introduced and why, file annotation is often your best tool. It shows you what commit was the last to modify each line of any file. So, if you see that a method in your code is buggy, you can annotate the file with <code>git blame</code> to see when each line of the method was last edited and by whom. This example uses the <code>-L</code> option to limit the output to lines 12 through 22:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">$ git blame -L 12,22 simplegit.rb ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 12) def show(tree = 'master') ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 13) command("git show #{tree}") ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 14) end ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 15) 9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 16) def log(tree = 'master') 79eaf55d (Scott Chacon 2008-04-06 10:15:08 -0700 17) command("git log #{tree}") 9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 18) end 9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 19) 42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 20) def blame(path) 42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 21) command("git blame #{path}") 42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 22) end</code></pre> </div> </div> <div class="paragraph"> <p>Notice that the first field is the partial SHA-1 of the commit that last modified that line. The next two fields are values extracted from that commit–the author name and the authored date of that commit – so you can easily see who modified that line and when. After that come the line number and the content of the file. Also note the <code>^4832fe2</code> commit lines, which designate that those lines were in this file’s original commit. That commit is when this file was first added to this project, and those lines have been unchanged since. This is a tad confusing, because now you’ve seen at least three different ways that Git uses the <code>^</code> to modify a commit SHA, but that is what it means here.</p> </div> <div class="paragraph"> <p>Another cool thing about Git is that it doesn’t track file renames explicitly. It records the snapshots and then tries to figure out what was renamed implicitly, after the fact. One of the interesting features of this is that you can ask it to figure out all sorts of code movement as well. If you pass <code>-C</code> to <code>git blame</code>, Git analyzes the file you’re annotating and tries to figure out where snippets of code within it originally came from if they were copied from elsewhere. For example, say you are refactoring a file named <code>GITServerHandler.m</code> into multiple files, one of which is <code>GITPackUpload.m</code>. By blaming <code>GITPackUpload.m</code> with the <code>-C</code> option, you can see where sections of the code originally came from:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">$ git blame -C -L 141,153 GITPackUpload.m f344f58d GITServerHandler.m (Scott 2009-01-04 141) f344f58d GITServerHandler.m (Scott 2009-01-04 142) - (void) gatherObjectShasFromC f344f58d GITServerHandler.m (Scott 2009-01-04 143) { 70befddd GITServerHandler.m (Scott 2009-03-22 144) //NSLog(@"GATHER COMMI ad11ac80 GITPackUpload.m (Scott 2009-03-24 145) ad11ac80 GITPackUpload.m (Scott 2009-03-24 146) NSString *parentSha; ad11ac80 GITPackUpload.m (Scott 2009-03-24 147) GITCommit *commit = [g ad11ac80 GITPackUpload.m (Scott 2009-03-24 148) ad11ac80 GITPackUpload.m (Scott 2009-03-24 149) //NSLog(@"GATHER COMMI ad11ac80 GITPackUpload.m (Scott 2009-03-24 150) 56ef2caf GITServerHandler.m (Scott 2009-01-05 151) if(commit) { 56ef2caf GITServerHandler.m (Scott 2009-01-05 152) [refDict setOb 56ef2caf GITServerHandler.m (Scott 2009-01-05 153)</code></pre> </div> </div> <div class="paragraph"> <p>This is really useful. Normally, you get as the original commit the commit where you copied the code over, because that is the first time you touched those lines in this file. Git tells you the original commit where you wrote those lines, even if it was in another file.</p> </div> </div> <div class="sect3"> <h3 id="_binary_search">Binary Search</h3> <div class="paragraph"> <p>Annotating a file helps if you know where the issue is to begin with. If you don’t know what is breaking, and there have been dozens or hundreds of commits since the last state where you know the code worked, you’ll likely turn to <code>git bisect</code> for help. The <code>bisect</code> command does a binary search through your commit history to help you identify as quickly as possible which commit introduced an issue.</p> </div> <div class="paragraph"> <p>Let’s say you just pushed out a release of your code to a production environment, you’re getting bug reports about something that wasn’t happening in your development environment, and you can’t imagine why the code is doing that. You go back to your code, and it turns out you can reproduce the issue, but you can’t figure out what is going wrong. You can bisect the code to find out. First you run <code>git bisect start</code> to get things going, and then you use <code>git bisect bad</code> to tell the system that the current commit you’re on is broken. Then, you must tell bisect when the last known good state was, using <code>git bisect good [good_commit]</code>:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">$ git bisect start $ git bisect bad $ git bisect good v1.0 Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo</code></pre> </div> </div> <div class="paragraph"> <p>Git figured out that about 12 commits came between the commit you marked as the last good commit (v1.0) and the current bad version, and it checked out the middle one for you. At this point, you can run your test to see if the issue exists as of this commit. If it does, then it was introduced sometime before this middle commit; if it doesn’t, then the problem was introduced sometime after the middle commit. It turns out there is no issue here, and you tell Git that by typing <code>git bisect good</code> and continue your journey:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">$ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing</code></pre> </div> </div> <div class="paragraph"> <p>Now you’re on another commit, halfway between the one you just tested and your bad commit. You run your test again and find that this commit is broken, so you tell Git that with <code>git bisect bad</code>:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">$ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table</code></pre> </div> </div> <div class="paragraph"> <p>This commit is fine, and now Git has all the information it needs to determine where the issue was introduced. It tells you the SHA-1 of the first bad commit and show some of the commit information and which files were modified in that commit so you can figure out what happened that may have introduced this bug:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">$ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04 Author: PJ Hyett <pjhyett@example.com> Date: Tue Jan 27 14:48:32 2009 -0800 secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config</code></pre> </div> </div> <div class="paragraph"> <p>When you’re finished, you should run <code>git bisect reset</code> to reset your HEAD to where you were before you started, or you’ll end up in a weird state:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">$ git bisect reset</code></pre> </div> </div> <div class="paragraph"> <p>This is a powerful tool that can help you check hundreds of commits for an introduced bug in minutes. In fact, if you have a script that will exit 0 if the project is good or non-0 if the project is bad, you can fully automate <code>git bisect</code>. First, you again tell it the scope of the bisect by providing the known bad and good commits. You can do this by listing them with the <code>bisect start</code> command if you want, listing the known bad commit first and the known good commit second:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-console" data-lang="console">$ git bisect start HEAD v1.0 $ git bisect run test-error.sh</code></pre> </div> </div> <div class="paragraph"> <p>Doing so automatically runs <code>test-error.sh</code> on each checked-out commit until Git finds the first broken commit. You can also run something like <code>make</code> or <code>make tests</code> or whatever you have that runs automated tests for you.</p> </div> </div> <div id="nav"><a href="/book/id/v2/Git-Tools-Rerere">prev</a> | <a href="/book/id/v2/Git-Tools-Submodules">next</a></div> </div> </div> </div> </div> <footer> <div class="site-source"> <a href="/site">About this site</a><br> Patches, suggestions, and comments are welcome. </div> <div class="sfc-member"> Git is a member of <a href="/sfc">Software Freedom Conservancy</a> </div> </footer> <a href="#top" class="no-js scrollToTop" id="scrollToTop" data-label="Scroll to top"> <img src="/images/icons/chevron-up@2x.png" width="20" height="20" alt="scroll-to-top"/> </a> <script src="/js/jquery-1.7.1.min.js"></script> <script src="/js/jquery-ui-1.8.18.custom.min.js"></script> <script src="/js/jquery.defaultvalue.js"></script> <script src="/js/session.min.js"></script> <script src="/js/application.min.js"></script> </div> </body> </html>