{ "sl_translate": "text, title, description", "pages": { "git": { "meta": { "title": "Learn Git- Git tutorials, workflows and commands | Atlassian Git Tutorial", "description": "Learn Git with beginner to advanced Git tutorials on workflows, git commands, git migration and code review.", "canonical": "https://www.atlassian.com/git"}, "topbar": { "text": "Getting Git Right", "cls": "home", "href": "/git" }, "flags": { "isSearch": false, "isTutorial": false }, "dom": [ { "tag": "DIV", "cls": " home-banner", "children": [ { "tag": "DIV", "cls": "g-row", "children": [ { "tag": "DIV", "cls": "g-column g-12-12 t-12-12 m-12-12 _hero-wrapper g-centered text-center", "children": [ { "tag": "IMG", "src": "/dam/jcr:c1326bc1-cede-4e55-b793-581f8370de17/hero%20(1).svg", "alt": "Getting Git Right", "cls": "svg"} , { "tag": "H1", "text": "Getting Git right, with tutorials, news and tips.", "cls": "_title icon-home-arrow-more"} ] } ] } ] } , { "tag": "DIV", "cls": " home-section home-about home-start", "children": [ { "tag": "DIV", "cls": "g-row container", "children": [ { "tag": "DIV", "cls": "g-column g-7-12 t-6-12 m-12-12", "children": [ { "tag": "H2", "text": "Git basics", "cls": ""} , { "tag": "DIV", "text": "
Git is a free and open source version control system, originally created by Linus Torvalds in 2005. Unlike older centralized version control systems such as SVN and CVS, Git is distributed: every developer has the full history of their code repository locally. This makes the initial clone of the repository slower, but subsequent operations such as commit, blame, diff, merge, and log dramatically faster.<\/p>\n\n
Git also has excellent support for branching, merging, and rewriting repository history, which has lead to many innovative and powerful workflows and tools. Pull requests are one such popular tool that allow teams to collaborate on Git branches and efficiently review each others code. Git is the most widely used version control system in the world today and is considered the modern standard for software development.<\/p>\n", "cls": ""} , { "tag": "H2", "text": "How Git works", "cls": ""} , { "tag": "DIV", "text": "
Here is a basic overview of how Git works:<\/p>\n\n
Mac OS/X<\/p>\n", "cls": ""} , { "tag": "A", "hashLink": "?section=git-for-mac-installer", "href": "/git/tutorials/install-git?section=git-for-mac-installer", "text": "Download Installer", "cls": ""} , { "tag": "A", "hashLink": "?section=homebrew", "href": "/git/tutorials/install-git?section=homebrew", "text": "Homebrew", "cls": ""} , { "tag": "A", "hashLink": "?section=macports", "href": "/git/tutorials/install-git?section=macports", "text": "MacPorts", "cls": ""} , { "tag": "A", "href": "https://www.sourcetreeapp.com/download/", "text": "Sourcetree", "cls": ""} , { "tag": "A", "hashLink": "?section=build-git-from-source-on-os-x", "href": "/git/tutorials/install-git?section=build-git-from-source-on-os-x", "text": "Build Git on Mac OS X", "cls": ""} , { "tag": "DIV", "text": "
Windows<\/p>\n", "cls": ""} , { "tag": "A", "hashLink": "?section=windows", "href": "/git/tutorials/install-git?section=windows", "text": "Git for Windows", "cls": ""} , { "tag": "A", "href": "https://www.sourcetreeapp.com/download/", "text": "Sourcetree", "cls": ""} , { "tag": "DIV", "text": "
Linux<\/p>\n", "cls": ""} , { "tag": "A", "hashLink": "?section=debian-ubuntu", "href": "/git/tutorials/install-git?section=debian-ubuntu", "text": "Debian / Ubuntu (apt-get)", "cls": ""} , { "tag": "A", "hashLink": "?section=fedora", "href": "/git/tutorials/install-git?section=fedora", "text": "Fedora (yum)", "cls": ""} , { "tag": "A", "hashLink": "?section=build-git-from-source-on-linux", "href": "/git/tutorials/install-git?section=build-git-from-source-on-linux", "text": "Build from source", "cls": ""} ] } ] } ] } ] } , { "tag": "DIV", "cls": "g-row home-section -popular", "children": [ { "tag": "DIV", "cls": " container", "children": [ { "tag": "DIV", "cls": "g-column g-3-12 t-5-12 m-12-12 g-centered text-center", "children": [ { "tag": "H3", "text": "Learn Git", "cls": "_label"} ] } , { "tag": "DIV", "cls": "g-column g-12-12 t-12-12 m-12-12 home-popular", "children": [ { "tag": "DIV", "cls": "g-row _sections", "children": [ { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-10-12 _group", "children": [ { "tag": "IMG", "src": "/dam/jcr:fa644f43-8e1e-40ea-a935-f494d3958c8a/git-hompage-interaction-48x48-01.svg", "alt": "Learn Git", "cls": ""} , { "tag": "H5", "text": "Learn Git", "cls": "_heading"} , { "tag": "A", "href": "/git/tutorials/learn-git-with-bitbucket-cloud", "text": "Learn Git with Bitbucket Cloud", "cls": ""} , { "tag": "A", "href": "/git/tutorials/learn-about-code-review-in-bitbucket-cloud", "text": "Learn about code review in Bitbucket Cloud", "cls": ""} , { "tag": "A", "href": "/git/tutorials/learn-branching-with-bitbucket-cloud", "text": "Learn Branching with Bitbucket Cloud", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-10-12 _group", "children": [ { "tag": "IMG", "src": "/dam/jcr:c6b94f6e-9c25-45ad-8d12-4b1221c85261/git-hompage-beginner-48x48-01.svg", "alt": "Git Beginner", "cls": ""} , { "tag": "H5", "text": "Beginner", "cls": "_heading"} , { "tag": "A", "href": "/git/tutorials/what-is-version-control", "text": "What is version control", "cls": ""} , { "tag": "A", "href": "/git/tutorials/what-is-git", "text": "What is Git", "cls": ""} , { "tag": "A", "href": "/git/tutorials/why-git", "text": "Why Git for your organization", "cls": ""} , { "tag": "A", "href": "/git/tutorials/install-git", "text": "Install Git", "cls": ""} , { "tag": "A", "href": "/git/tutorials/atlassian-git-cheatsheet", "text": "Git cheat sheet", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-10-12 _group", "children": [ { "tag": "IMG", "src": "/dam/jcr:e833d09a-8ef3-4b14-a4cd-e2d0630955f7/git-hompage-getting-started-48x48-02.svg", "alt": "Getting Started", "cls": ""} , { "tag": "H5", "text": "Getting Started", "cls": "_heading"} , { "tag": "A", "href": "/git/tutorials/setting-up-a-repository", "text": "Setting up a repository", "cls": ""} , { "tag": "A", "href": "/git/tutorials/saving-changes", "text": "Saving changes", "cls": ""} , { "tag": "A", "href": "/git/tutorials/inspecting-a-repository", "text": "Inspecting a repository", "cls": ""} , { "tag": "A", "href": "/git/tutorials/undoing-changes", "text": "Undoing changes", "cls": ""} , { "tag": "A", "href": "/git/tutorials/rewriting-history", "text": "Rewriting history", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-10-12 _group", "children": [ { "tag": "IMG", "src": "/dam/jcr:f7aedcae-3abb-4b08-bccd-c85ec7cded1a/git-hompage-collaborating-48x48-04.svg", "alt": "Collaborating", "cls": ""} , { "tag": "H5", "text": "Collaborating", "cls": "_heading"} , { "tag": "A", "href": "/git/tutorials/syncing", "text": "Syncing", "cls": ""} , { "tag": "A", "href": "/git/tutorials/making-a-pull-request", "text": "Making a Pull Request", "cls": ""} , { "tag": "A", "href": "/git/tutorials/using-branches", "text": "Using Branches", "cls": ""} , { "tag": "A", "href": "/git/tutorials/comparing-workflows", "text": "Comparing Workflows", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-10-12 _group", "children": [ { "tag": "IMG", "src": "/dam/jcr:093e411c-df76-4c2d-96d7-7117f0cb706a/git-hompage-migrating-to-git-48x48-03.svg", "alt": "Migrating to Git", "cls": ""} , { "tag": "H5", "text": "Migrating to Git", "cls": "_heading"} , { "tag": "A", "href": "/git/tutorials/svn-to-git-prepping-your-team-migration", "text": "SVN to Git - prepping for the migration", "cls": ""} , { "tag": "A", "href": "/git/tutorials/migrating-overview", "text": "Migrate to Git from SVN", "cls": ""} , { "tag": "A", "href": "/git/tutorials/perforce-git", "text": "Perforce to Git - why to make the move", "cls": ""} , { "tag": "A", "href": "/git/tutorials/perforce-git-migration", "text": "Migrating from Perforce to Git", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-10-12 _group", "children": [ { "tag": "IMG", "src": "/dam/jcr:eeb9975f-c7da-47be-a9c9-a376970d5c4b/git-hompage-advanced-tips-48x48-05.svg", "alt": "Advanced Tips", "cls": ""} , { "tag": "H5", "text": "Advanced Tips", "cls": "_heading"} , { "tag": "A", "href": "/git/tutorials/advanced-overview", "text": "Advanced Git Tutorials", "cls": ""} , { "tag": "A", "href": "/git/tutorials/merging-vs-rebasing", "text": "Merging vs. Rebasing", "cls": ""} , { "tag": "A", "href": "/git/tutorials/resetting-checking-out-and-reverting", "text": "Reset, Checkout, and Revert", "cls": ""} , { "tag": "A", "href": "/git/tutorials/git-log", "text": "Advanced Git log", "cls": ""} , { "tag": "A", "href": "/git/tutorials/git-hooks", "text": "Git Hooks", "cls": ""} , { "tag": "A", "href": "/git/tutorials/refs-and-the-reflog", "text": "Refs and the Reflog", "cls": ""} , { "tag": "A", "href": "/git/tutorials/git-lfs", "text": "Git LFS", "cls": ""} ] } ] } , { "tag": "DIV", "cls": "g-row", "children": [ { "tag": "DIV", "cls": "g-column g-12-12 t-12-12 m-12-12", "children": [ { "tag": "A", "href": "/git/tutorials", "text": "See all tutorials", "cls": "see-all"} ] } ] } ] } ] } ] } , { "tag": "DIV", "cls": "g-row home-section -posts", "children": [ { "tag": "DIV", "cls": " container home-post", "children": [ { "tag": "DIV", "cls": "g-column g-3-12 t-5-12 m-12-12 g-centered text-center", "children": [ { "tag": "H3", "text": "Top Posts", "cls": "_label"} ] } , { "tag": "DIV", "cls": "g-column g-8-12 t-12-12 m-10-12 _item clear g-centered text-center", "children": [ { "tag": "IMG", "src": "/dam/jcr:a70fc026-652a-43e9-89d0-8f753349d49a/sarah-goff-dupont.png", "alt": "Sarah Goff-Dupont", "cls": "_avatar"} , { "tag": "H6", "text": "Sarah Goff-Dupont", "cls": ""} , { "tag": "H3", "text": "Five tips for CI-friendly Git repos", "cls": ""} , { "tag": "A", "href": "/git/articles/ci-friendly-git-repos", "text": "Read article", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-8-12 t-12-12 m-10-12 _item clear g-centered text-center", "children": [ { "tag": "IMG", "src": "/dam/jcr:288f5c28-5a14-4f98-a35b-364b5ec48dcf/matt-shelton.png", "alt": "Matt Shelton", "cls": "_avatar"} , { "tag": "H6", "text": "Matt Shelton", "cls": ""} , { "tag": "H3", "text": "Git or SVN? How Nuance Healthcare chose a Git branching model?", "cls": ""} , { "tag": "A", "href": "/git/articles/git-or-svn-git-branching-model", "text": "Read article", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-8-12 t-12-12 m-10-12 _item clear g-centered text-center", "children": [ { "tag": "IMG", "src": "/dam/jcr:288f5c28-5a14-4f98-a35b-364b5ec48dcf/matt-shelton.png", "alt": "Matt Shelton", "cls": "_avatar"} , { "tag": "H6", "text": "Matt Shelton", "cls": ""} , { "tag": "H3", "text": "Dealing with Maven dependencies when switching to Git", "cls": ""} , { "tag": "A", "href": "/git/articles/maven-dependencies-versions-merging", "text": "Read article", "cls": ""} ] } , { "tag": "A", "href": "/git/articles", "text": "See All Articles", "cls": "see-all"} ] } ] } , { "tag": "DIV", "cls": "g-row home-section -glossary", "children": [ { "tag": "DIV", "cls": " container", "children": [ { "tag": "DIV", "cls": "g-column g-3-12 t-5-12 m-12-12 g-centered text-center", "children": [ { "tag": "H3", "text": "Did you know...", "cls": "_label"} ] } , { "tag": "DIV", "cls": " home-glossary", "children": [ { "tag": "DIV", "cls": "g-column g-9-12 t-12-12 m-12-12 g-centered text-center", "children": [ { "tag": "H3", "text": "Branch", "cls": "_def"} ] } , { "tag": "DIV", "cls": "g-column g-6-12 t-12-12 m-12-12 g-centered text-center", "children": [ { "tag": "DIV", "text": "
Definition: <\/span><\/strong>A branch represents an independent line of development. Branches serve as an abstraction for the edit/stage/commit process discussed in Git Basics, the first module of this series. You can think of them as a way to request a brand new working directory, staging area, and project history. New commits are recorded in the history for the current branch, which results in a fork in the history of the project.<\/span><\/p>\n", "cls": ""} , { "tag": "A", "href": "/git/glossary", "text": "See All References", "cls": "see-all"} ] } ] } ] } ] } ] }, "git/articles": { "meta": { "title": "Git Articles | Atlassian Git Tutorial", "description": "Learn how other developers are using Git. Tools, tips, tricks, best practices, and more.", "canonical": "https://www.atlassian.com/git/articles"}, "topbar": { "text": "Articles", "cls": "articles", "href": "/git/articles" }, "flags": { "isSearch": false, "isTutorial": false }, "dom": [ { "tag": "DIV", "cls": " articles-index", "children": [ { "tag": "DIV", "cls": " _header", "children": [ { "tag": "IMG", "src": "/dam/jcr:49baa36c-6b25-4cc8-9ea5-deddb044fc9f/hero.svg", "alt": "Git Articles Hero", "cls": "_hero"} , { "tag": "DIV", "cls": " _header-group", "children": [ { "tag": "DIV", "cls": "g-column g-8-12 t-12-12 m-10-12 g-centered text-center", "children": [ { "tag": "H5", "text": "Featured Article", "cls": ""} , { "tag": "DIV", "text": " Sarah Goff-Dupont | November 14 2014<\/p>\n", "cls": ""} ] } ] } ] } ] } , { "tag": "DIV", "cls": " articles-page container", "children": [ { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Git or SVN? How Nuance Healthcare chose a Git branching model?", "cls": ""} , { "tag": "DIV", "text": " This is a guest post from Matt Shelton at Nuance Healthcare. This is the first post in a series about his team moving from Subversion to Git, why they did it, and what we encountered along the way. Matt is also speaking on this topic at Atlassian Summit 2015<\/a>. This series will feature everything he couldn’t say in his 30 minute talk, with more context.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/git-or-svn-git-branching-model", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Dealing with Maven dependencies when switching to Git", "cls": ""} , { "tag": "DIV", "text": " So we're moving to Git<\/a> and we like git-flow. Now what? Let's test it all out! My team is great. They threw together a hit list of developer workflows in Confluence<\/a>, all based on what we had been doing as a team and all of the weird things they thought we might have to do in the future. Then, in a project structure mirroring our own (but with no code in it - just a pom.xml), tried every workflow.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/maven-dependencies-versions-merging", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Pulling the Trigger: Migrating from SVN to Git", "cls": ""} , { "tag": "DIV", "text": " We're moving to Git<\/a>, and we figured out how to use git-flow and Maven together<\/a> in an efficient development workflow. Before I get into what our workflow looks like now, it's important to know where we came from.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/pulling-the-trigger-git-migration", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "10 Years of Git", "cls": ""} , { "tag": "DIV", "text": " 10 years ago Linus Torvalds started writing code for a new distributed version control system on a Sunday and only a mere few days later, the world was given the gift of Git.<\/p>", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/10-years-of-git", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Git guilt, blame, and code review", "cls": ""} , { "tag": "DIV", "text": " I've been doing a bit of traveling lately on the second leg of the Getting Git Right<\/a> tour. It's been a blast meeting so many devs from around the world. It's been particularly incredible to see how much git adoption has grown amongst attendees in the few months since we did the first leg of the tour. When we presented in July, almost all attendees raised their hand when we asked "Who's using git?".<\/em><\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/git-guilt-blame-and-code-review", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Git: Automatic Merges With Server Side Hooks (For The Win!)", "cls": ""} , { "tag": "DIV", "text": " Enterprise DVCS Workflows are settling and patterns are consolidating. The flexibility git<\/a> gives teams is so broad that even within a single company different teams might use different approaches to code sharing and collaboration.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/git-automatic-merges-with-server-side-hooks", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Git Forks And Upstreams: How-to and a cool tip", "cls": ""} , { "tag": "DIV", "text": " There are tons<\/a> and<\/a> then<\/a> some<\/a> useful guides on how to keep your Following the git 2.0.0 release two-and-a-half months ago we're being treated to a new minor version of git, 2.1.0, with a host of exciting new features!<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/whats-new-in-git-2-1", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Core Concept, Workflows And Tips", "cls": ""} , { "tag": "DIV", "text": " Including submodules as part of your Git development allows you to include other projects in your codebase, keeping their history separate but synchronized with yours. It's a convenient way to solve the vendor library and dependency problems. As usual with everything The question is simple: In a software team using The Internet is full of articles on why you should<\/a> not<\/a> use<\/a> Git submodules. I mostly agree, although I am not so harsh in my evaluation. As I explained in a previous post<\/a>, While Mercurial has a well defined (albeit internal) API<\/a> that can be used to write extensions<\/a> that extend the functionality of Mercurial, git's extension model follows the Unix philosophy<\/a> of composing small, simple programs to achieve a similar effect. What that means is that git "extensions" can be written in any language and by following a few simple rules it's still possible to add commands that appear as if they were built-in.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/extending-git", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Pull request proficiency: Fetching abilities unlocked!", "cls": ""} , { "tag": "DIV", "text": " Nowadays applying a fix to a project is as easy as creating a fork<\/a> - which conjures up a full remote copy of the project for you to hack on - selecting the file you want to change, pressing Edit<\/a> and committing your fixes.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/pull-request-proficiency-fetching-abilities-unlocked", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Git and project dependencies", "cls": ""} , { "tag": "DIV", "text": " Consider the following questions. How do you handle project dependencies with Many teams have already migrated to git<\/a> is an advanced tool. It features a philosophy that is dear to my heart: to treat developers as smart and responsible folks. This means that a lot of power is at your fingertips. The power to also shoot yourself in the foot - arguably with a titanium vest on - but shoot yourself nonetheless.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/titanium-armor-recovering-from-various-disasters", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Trust the merge and branch simplification musings", "cls": ""} , { "tag": "DIV", "text": " Our recent webinar<\/a> featuring product rock stars Jens Schumacher<\/a> and Ken Olofsen<\/a> gave a great overview of Before joining Atlassian, I'd been working on various projects that still used Subversion (SVN) as their version control system. I had moved to Git already years before, and I wanted to keep using it as much as possible.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/use-git-even-if-your-team-doesnt-git-svn-tips-and-tricks", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "What You Need To Know About The New Git 1.8.2 Release", "cls": ""} , { "tag": "DIV", "text": " I love scouring the release notes of my favorite tools for hidden (or not so hidden) gems. It's a little bit like Christmas every time. I get that nice feeling of anticipation and curiosity when new versions are released of my faithful OSX open source window manager Slate<\/a>, on Rails<\/a>, Django<\/a>, CoffeeScript<\/a> and of course Git<\/a> and many others.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/what-you-need-to-know-about-the-new-git-1-8-2-release", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "What You Need To Know About The New Git 1.8.3", "cls": ""} , { "tag": "DIV", "text": " Whether you use While we wait for the next major I know you are all busy with looting marathons<\/a> in DayZ<\/a> but bear with me. Something is worth checking out today. The latest This major release of 10 years ago Linus Torvalds started writing code for a new distributed version control system on a Sunday and only a mere few days later, the world was given the gift of Git. Git has helped teams big and small work faster while becoming more distributed and has left its mark with cheap local branching, easier code review, flexible work flows and so much more. Over the last decade Git has seen exponential growth and has become the most popular version control system today. Take a walk down memory lane to see how Git has evolved over the years and join us in celebrating the history of Git.<\/p>", "cls": "intro"} , { "tag": "DIV", "cls": " timeline", "children": [ { "tag": "DIV", "cls": " item small start", "children": [ { "tag": "DIV", "cls": "g-row content", "children": [ { "tag": "DIV", "text": " START<\/p>\n", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " item large announced", "children": [ { "tag": "DIV", "cls": "g-row content", "children": [ { "tag": "H3", "text": "April 2005", "cls": "date"} , { "tag": "H3", "text": "Git project announced & becomes self-hosting", "cls": ""} , { "tag": "DIV", "text": " Created by Linus Torvalds<\/p>\n", "cls": "desc"} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " The creator of Linux, Linus Torvalds began the development of Git on April 3, 2005 and announced the project on April 6. Just one day later the Git project was self-hosting.<\/p>\n", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " kinematic animated", "children": [ { "tag": "IMG", "src": "/dam/jcr:cf2c63f1-41b7-4c98-a48d-5a884efe965b/new-announced@2x.png", "alt": "Git Announced", "cls": ""} ] } ] } , { "tag": "DIV", "cls": "g-row item tiny first-merge", "children": [ { "tag": "DIV", "cls": " content left", "children": [ { "tag": "H3", "text": "April 2005", "cls": "date"} , { "tag": "H3", "text": "1st merge of multiple branches", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Torvalds merges multiple branches for the first time and according to him, it came out correctly and 100% according to plan in very little time.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": "g-row item tiny junio-hamano", "children": [ { "tag": "DIV", "cls": " content bottom", "children": [ { "tag": "H3", "text": "July 2005", "cls": "date"} , { "tag": "H3", "text": "Junio Hamano takes over maintenance of Git project", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Torvalds has stated that one of the biggest successes in his life was actually recognizing how good a developer Junio Hamano was on Git, and trusting him enough to just ask if he would be willing to maintain the project.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item large git-1", "children": [ { "tag": "DIV", "cls": "g-row content", "children": [ { "tag": "H3", "text": "December 2005", "cls": "date"} , { "tag": "H3", "text": "Git 1.0 released", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Before the 1.0 version, Git had been in production use by the Linux kernel team for a good amount of time. 1.0 is normally a significant milestone, but for Git it meant some documentation updates, clone/fetch enhancements and bug fixes.<\/p>\n", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " kinematic animated", "children": [ { "tag": "IMG", "src": "/dam/jcr:ba62c92b-da50-4835-9d23-429dcb0b6e56/new-git-1@2x.png", "alt": "Git Announced", "cls": ""} ] } ] } , { "tag": "DIV", "cls": "g-row item tiny torvalds-google", "children": [ { "tag": "DIV", "cls": " content top", "children": [ { "tag": "H3", "text": "May 2007", "cls": "date"} , { "tag": "H3", "text": "Linus Torvalds gives Git talk at Google", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Torvalds' tech talk at Google covered his creation of the version control system, Git. He explains his love for distributed source control in general and highlights that with a distributed tool, no single place is vital to your data, centralized version control does not scale for Linux-kernel sized projects. Plus, distributed tools work offline, with full history.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item tiny original-pr", "children": [ { "tag": "DIV", "cls": " content left solid", "children": [ { "tag": "H3", "text": "February 2008", "cls": "date"} , { "tag": "H3", "text": "Original pull request", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " During its beta, GitHub released a feature called pull requests. At the time, pull requests were limited to notifying developers when they needed to pull changes from a forked repo, or to ask developers to pull. It could also notify someone that you pushed a new feature to a non-master branch.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item large github-launch", "children": [ { "tag": "DIV", "cls": " content", "children": [ { "tag": "H3", "text": "April 2008", "cls": "date"} , { "tag": "H3", "text": "GitHub site launched", "cls": ""} , { "tag": "DIV", "text": " Founded by Tom Preston-Werner, Chris Wanstrath, and PJ Hyett<\/p>\n", "cls": "desc"} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Development of the GitHub site began in October 2007 and was in beta until April, 2008. Today, GitHub is known for their open source community and hosts over 20.7 million repositories.<\/p>\n", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " kinematic animated", "children": [ { "tag": "IMG", "src": "/dam/jcr:17777b30-69d5-40aa-90e2-905299dcd708/new-github-launch@2x.png", "alt": "Git Announced", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " item tiny gist", "children": [ { "tag": "DIV", "cls": " content right", "children": [ { "tag": "H3", "text": "July 2008", "cls": "date"} , { "tag": "H3", "text": "Gist announced", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Gist is a simple way to share code snippets and pastes with others. Upon their creation, gists expanded on pastebins (public place to paste source code) by adding version control for code snippets, easy forking, SSL encryption for private pastes and the ability to be pushed and pulled using Git (since each Gist has its own repository.)<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item graph git-searches", "children": [ { "tag": "H3", "text": "\"Git Download\" Keyword Search Trend over Time", "cls": ""} , { "tag": "DIV", "cls": " _hero is-active", "children": [ { "tag": "IMG", "src": "/dam/jcr:94f50197-f9e1-4545-88fb-33b6b085ed99/new-git-searches.svg", "alt": "Git Searches", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " item large skyrocket", "children": [ { "tag": "DIV", "cls": "g-row content", "children": [ { "tag": "H3", "text": "January 2010", "cls": "date"} , { "tag": "H3", "text": "Git installations skyrocket", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Installations on Debian Linux show that developers were taking huge notice of Git and starting to make the switch from SVN, CVS and Mercurial.<\/p>\n", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " kinematic animated", "children": [ { "tag": "IMG", "src": "/dam/jcr:bfe3e066-5af0-4693-869e-68745d0d06c3/new-skyrocket@2x.png", "alt": "Git Announced", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " item tiny sourcetree", "children": [ { "tag": "DIV", "cls": " content top", "children": [ { "tag": "H3", "text": "April 2010", "cls": "date"} , { "tag": "H3", "text": "Sourcetree founded by Steve Streeting", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Sourcetree is a free Git and Mercurial client for Mac or Windows. Atlassian acquired Sourcetree in October 2011. It allows developers to manage and interface with multiple Git and Mercurial repositories visually through a client instead of the command line.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item tiny pull-requests-2", "children": [ { "tag": "DIV", "cls": " content left solid", "children": [ { "tag": "H3", "text": "August 2010", "cls": "date"} , { "tag": "H3", "text": "Pull requests 2.0", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Pull requests were revamped to not only take into account what a developer would like pulled, but also where those changes needed to be applied. They now included a discussion view that allowed a conversation to happen about the changes right in the pull request. The discussion view showed all pull request related activity – the actual pull request, push follow up commits, or commit notes so you could watch changes evolve over time.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item large git-annex-launch", "children": [ { "tag": "DIV", "cls": "g-row content", "children": [ { "tag": "H3", "text": "October 2010", "cls": "date"} , { "tag": "H3", "text": "Git-annex launches", "cls": ""} , { "tag": "DIV", "text": " Large Git file management without checking file contents into Git<\/p>\n", "cls": "desc"} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Git-annex is useful when dealing with files larger than Git can easily handle, whether due to limitations in memory, time, or disk space. The contents of annexed files are not stored in Git, only the names of the files and some other metadata remain there. Git-annex is free software, written in Haskell.<\/p>\n", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " kinematic animated", "children": [ { "tag": "IMG", "src": "/dam/jcr:c724389b-0f31-4229-9d5e-4963be14c7c8/new-git-annex-launch@2x.png", "alt": "Git Announced", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " item tiny installations-surpass", "children": [ { "tag": "DIV", "cls": " content right", "children": [ { "tag": "H3", "text": "January 2011", "cls": "date"} , { "tag": "H3", "text": "Git installations surpass all other version control systems", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Over the course of a year, Git installations on Debian Linux managed to surpass Bzr, CVS, Mercurial, SVN & Darcs going from 5,000 submitters to 35,000.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item tiny pull-requests-2", "children": [ { "tag": "DIV", "cls": " content left solid", "children": [ { "tag": "H3", "text": "September 2011", "cls": "date"} , { "tag": "H3", "text": "Gitlab founded", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Dmitriy Zaporozhets and Valeriy Sizov founded Gitlab in Ukraine. Originally, Gitlab was a free and open source software, but in July 2013, Gitlab split into a community edition & an enterprise edition.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item graph git-meetups", "children": [ { "tag": "H3", "text": "Git MeetUp Groups around the World", "cls": ""} , { "tag": "DIV", "cls": " _hero is-active", "children": [ { "tag": "IMG", "src": "/dam/jcr:b3789611-69b4-4df5-9d0e-de834b9529bf/new-git-meetups-01.svg", "alt": "Git meetups around the world", "cls": ""} ] } , { "tag": "DIV", "text": " 1 year after Bitbucket joined Atlassian, it added Git support. Today, Bitbucket is used by professional software teams to host, manage, and share Git and Mercurial repositories in the cloud. It is used by companies worldwide such as Salesforce, Tesla & PayPal.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item large stash", "children": [ { "tag": "DIV", "cls": "g-row content", "children": [ { "tag": "H3", "text": "May 2012", "cls": "date"} , { "tag": "H3", "text": "Atlassian releases Stash 1.0", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Stash joins the Atlassian family as an on-premise Git repository management tool that is secure, fast and enterprise-grade. Today, Stash is known as the only collaborative Git solution that massively scales and is used worldwide by companies such as Netflix, Nordstrom & NASA.<\/p>\n", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " kinematic animated", "children": [ { "tag": "IMG", "src": "/dam/jcr:3e7c18e2-f889-4717-8e58-f7cf8f2ef36a/new-stash@2x.png", "alt": "Git Announced", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " item tiny torvalds-pr", "children": [ { "tag": "DIV", "cls": " content right", "children": [ { "tag": "H3", "text": "May 2012", "cls": "date"} , { "tag": "H3", "text": "Bitbucket exceeds half a million repos managed", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Git was seeing such exponential growth that Bitbucket's repos were 40% Git just 6 months after Bitbucket introduced Git support to its previously Mercurial-only offering.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item graph git-usage enter active", "children": [ { "tag": "H3", "text": "Git Usage by Developers over Time", "cls": ""} , { "tag": "DIV", "cls": " _hero is-active", "children": [ { "tag": "IMG", "src": "/dam/jcr:0c12a1d9-2210-434c-ae2a-ff3fc83eba15/new-git-usage-01-01.svg", "alt": "Git usage over time", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " item tiny git-2", "children": [ { "tag": "DIV", "cls": " content top", "children": [ { "tag": "H3", "text": "March 2014", "cls": "date"} , { "tag": "H3", "text": "Git 2.0 released", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " This major release of Git involved some default changes, one of the largest being the gitpush default behavior. It originally was set to matching, but with 2.0, the default changed to simple, meaning it would push only your current branch to the remote branch with the same name. Other notable changes were the git add path now equating to git add -A path, git svn default prefixes changed and now placed remote-tracking branches under refs/remotes/origin (instead of directly under refs/remote), and non breaking changes got grouped by demand.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item large surpass-svn enter", "children": [ { "tag": "DIV", "cls": "g-row content", "children": [ { "tag": "H3", "text": "June 2014", "cls": "date"} , { "tag": "H3", "text": "Developers usage of Git surpasses SVN", "cls": ""} , { "tag": "DIV", "text": " Yearly Eclipse Community Survey calls out Git as the #1 Code management tool<\/p>\n", "cls": "desc"} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Every June the Eclipse Community Survey polls software developers to learn more about the tools they are using. 2014 was Git's year and it was finally announced that Git's usage by developers had surpassed SVN as the #1 code management tool. My how far Git had come in 9 years' time.<\/p>\n", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " kinematic animated", "children": [ { "tag": "IMG", "src": "/dam/jcr:6f6aa56a-0960-4df5-9d61-9c346ddcb153/new-surpass-svn@2x.png", "alt": "Git Announced", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " item tiny snippets", "children": [ { "tag": "DIV", "cls": " content top", "children": [ { "tag": "H3", "text": "March 2015", "cls": "date"} , { "tag": "H3", "text": "Snippets launch", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Atlassian launched Snippets for Bitbucket as a quick and easy way to share code, notes, and pastes with your team.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item tiny bitbucket-lfs", "children": [ { "tag": "DIV", "cls": " content left solid", "children": [ { "tag": "H3", "text": "October 2016", "cls": "date"} , { "tag": "H3", "text": "Bitbucket Supports Git LFS", "cls": ""} , { "tag": "A", "hashLink": "#", "text": "info", "cls": "info"} , { "tag": "DIV", "cls": " item-modal", "children": [ { "tag": "DIV", "text": " Developers using large binary files and rich media can now collaborate on 80+ file types of any size and store all their files in one place. Git LFS stores your large files externally and keeps your actual Git repository lightweight, resulting in faster cloning and fetching times.<\/p>\n", "cls": ""} ] } ] } ] } , { "tag": "DIV", "cls": " item huge whats-next", "children": [ { "tag": "DIV", "cls": "g-row content", "children": [ { "tag": "A", "href": "/git/tutorials", "text": "What's next?", "cls": ""} ] } , { "tag": "DIV", "cls": " kinematic animated", "children": [ { "tag": "IMG", "src": "/dam/jcr:ea36594b-eb07-4d1e-aaa3-9660f97f678c/new-whats-next@2x.png", "alt": "Git Announced", "cls": ""} ] } ] } ] } ] } , { "tag": "DIV", "cls": " sources", "children": [ { "tag": "H4", "text": "Sources", "cls": ""} , { "tag": "DIV", "cls": "g-row source-links", "children": [ { "tag": "DIV", "cls": " col-1", "children": [ { "tag": "A", "href": "http://marc.info/?l=git&m=117254154130732", "text": "http://marc.info/?l=git&m=117254154130732", "cls": ""} , { "tag": "A", "href": "http://marc.info/?l=git&m=111377572329534", "text": "http://marc.info/?l=git&m=111377572329534", "cls": ""} , { "tag": "A", "href": "http://marc.info/?l=git&m=112243466603239", "text": "http://marc.info/?l=git&m=112243466603239", "cls": ""} , { "tag": "A", "href": "http://lwn.net/Articles/165127/", "text": "http://lwn.net/Articles/165127/", "cls": ""} , { "tag": "A", "href": "http://techcrunch.com/2012/04/19/an-interview-with-millenium-technology-prize-finalist-linus-torvalds/", "text": "http://techcrunch.com/2012/04/19/an-interview-with-millenium-technology-prize-finalist-linus-torvalds/", "cls": ""} , { "tag": "A", "href": "http://lwn.net/Articles/165127/", "text": "http://lwn.net/Articles/165127/", "cls": ""} , { "tag": "A", "href": "http://lwn.net/Articles/165127/", "text": "http://lwn.net/Articles/165127/", "cls": ""} , { "tag": "A", "href": "https://www.youtube.com/watch?v=4XpnKHJAok8", "text": "https://www.youtube.com/watch?v=4XpnKHJAok8", "cls": ""} , { "tag": "A", "href": "https://github.com/blog/3-oh-yeah-there-s-pull-requests-now", "text": "https://github.com/blog/3-oh-yeah-there-s-pull-requests-now", "cls": ""} , { "tag": "A", "href": "https://github.com/blog/40", "text": "https://github.com/blog/40", "cls": ""} , { "tag": "A", "href": "http://en.wikipedia.org/wiki/GitHub", "text": "http://en.wikipedia.org/wiki/GitHub", "cls": ""} , { "tag": "A", "href": "https://github.com/blog/118-here-s-the-gist-of-it", "text": "https://github.com/blog/118-here-s-the-gist-of-it", "cls": ""} ] } , { "tag": "DIV", "cls": " col-1", "children": [ { "tag": "A", "href": "http://www.scalevp.com/github-the-new-locus-of-software-development", "text": "http://www.scalevp.com/github-the-new-locus-of-software-development", "cls": ""} , { "tag": "A", "href": "https://blogs.atlassian.com/2011/10/press_release_atlassian_acquires_sourcetree_adds_git_support_to_bitbucket_code_hosting/", "text": "https://blogs.atlassian.com/2011/10/press_release_atlassian_acquires_sourcetree_adds_git_support_to_bitbucket_code_hosting/", "cls": ""} , { "tag": "A", "href": "https://github.com/blog/712-pull-requests-2-0", "text": "https://github.com/blog/712-pull-requests-2-0", "cls": ""} , { "tag": "A", "href": "http://lwn.net/Articles/419241/", "text": "http://lwn.net/Articles/419241/", "cls": ""} , { "tag": "A", "href": "http://www.scalevp.com/github-the-new-locus-of-software-development", "text": "http://www.scalevp.com/github-the-new-locus-of-software-development", "cls": ""} , { "tag": "A", "href": "https://about.gitlab.com/team/", "text": "https://about.gitlab.com/team/", "cls": ""} , { "tag": "A", "href": "http://en.wikipedia.org/wiki/GitLab", "text": "http://en.wikipedia.org/wiki/GitLab", "cls": ""} , { "tag": "A", "href": "https://blog.bitbucket.org/2011/10/03/bitbucket-now-rocks-git/", "text": "https://blog.bitbucket.org/2011/10/03/bitbucket-now-rocks-git/", "cls": ""} , { "tag": "A", "href": "https://blogs.atlassian.com/2012/05/atlassian-stash-enterprise-git-repository-management/", "text": "https://blogs.atlassian.com/2012/05/atlassian-stash-enterprise-git-repository-management/", "cls": ""} , { "tag": "A", "href": "http://sdtimes.com/git-2-0-0-released/", "text": "http://sdtimes.com/git-2-0-0-released/", "cls": ""} , { "tag": "A", "href": "http://eclipse.dzone.com/articles/eclipse-community-survey-2014", "text": "http://eclipse.dzone.com/articles/eclipse-community-survey-2014", "cls": ""} ] } ] } ] } ] } ] } ] }, "git/articles/alternatives-to-git-submodule-git-subtree": { "meta": { "title": "Alternatives To Git Submodule: Git Subtree | Atlassian Git Tutorial", "description": "Atlassian Git Tutorial", "canonical": "https://www.atlassian.com/blog/git/alternatives-to-git-submodule-git-subtree"}, "topbar": { "text": "Articles", "cls": "articles", "href": "/git/articles" }, "flags": { "isSearch": false, "isTutorial": false }, "dom": [ { "tag": "DIV", "cls": " articles-header", "children": [ { "tag": "DIV", "cls": "g-column g-12-12 t-12-12 m-10-12 _header g-centered text-center", "children": [ { "tag": "H1", "text": "Alternatives To Git Submodule: Git Subtree", "cls": ""} , { "tag": "IMG", "src": "/dam/jcr:1a355490-1c55-42a2-aa4a-30b260d0163e/nicola-paolucci.png", "alt": "Nicola Paolucci", "cls": "_avatar"} , { "tag": "H6", "text": "Nicola Paolucci", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " articles-content", "children": [ { "tag": "A", "href": "/git/articles", "text": "Back to list", "cls": "_back"} , { "tag": "DIV", "cls": "g-row container", "children": [ { "tag": "DIV", "cls": "g-column g-12-12 t-12-12 m-10-12 g-centered text-left", "children": [ { "tag": "DIV", "text": " The Internet is full of articles on why you should<\/a> not<\/a> use<\/a> Git submodules. I mostly agree, although I am not so harsh in my evaluation. Are there alternatives? The answer is: yes! There are (at least) two tools that can help track the history of software dependencies in your project while allowing you to keep using git: <\/p>", "cls": ""} , { "tag": "DIV", "text": " In this post I will be looking at As a working example I run to my usual use case. How do I easily store and keep up to date the vim plugins used in my dotfiles<\/a>?<\/p>", "cls": ""} , { "tag": "H2", "text": "Why use subtree instead of submodule?", "cls": ""} , { "tag": "DIV", "text": " There are several reasons why you might find In my opinion the drawbacks are acceptable:<\/p>", "cls": ""} , { "tag": "DIV", "text": " Let me show you the canonical example of tracking a vim plug-in using If you just want a couple of one liners to cut and paste just read this paragraph.<\/p>", "cls": ""} , { "tag": "DIV", "text": " First add the (The common practice is to not store the entire history of the sub-project in your main repository, but If you want to preserve it just omit the The above command produces this output:<\/p>", "cls": ""} , { "tag": "DIV", "text": " As you can see this records a If after a while you want to update the code of the plugin from the This is very quick and painless but the commands are slightly lengthy and hard to remember. We can make the commands shorter by adding the sub-project as a remote.<\/p>", "cls": ""} , { "tag": "H3", "text": "Adding the sub-project as a remote", "cls": ""} , { "tag": "DIV", "text": " Adding the subtree as a remote allows us to refer to it in shorter form:<\/p>", "cls": ""} , { "tag": "DIV", "text": " Now we can add the subtree (as before), but now we can refer to the remote in short form:<\/p>", "cls": ""} , { "tag": "DIV", "text": " The command to update the sub-project at a later date becomes:<\/p>", "cls": ""} , { "tag": "DIV", "text": " We can freely commit our fixes to the sub-project in our local working directory now.<\/p>", "cls": ""} , { "tag": "DIV", "text": " When it's time to contribute back to the Now we can use the After this we're ready and we can open a Add the dependency as a simple git remote<\/a>:<\/p>", "cls": ""} , { "tag": "DIV", "text": " Before reading the contents of the dependency into the repository it's important to record a merge so that we can track the entire tree history of the plug-in up to this point:<\/p>", "cls": ""} , { "tag": "DIV", "text": " Which outputs:<\/p>", "cls": ""} , { "tag": "DIV", "text": " We then read the content of the latest tree-object in the plugin repository into our working directory ready to be committed:<\/p>", "cls": ""} , { "tag": "DIV", "text": " Now we can commit (and it will be a merge commit that will preserve the history of the tree we read):<\/p>", "cls": ""} , { "tag": "DIV", "text": " When we want to update the project we can now After having used Follow me @durdn<\/a> and the awesome @Bitbucket <\/a>team for more Git rocking.<\/p>\n", "cls": ""} , { "tag": "DIV", "text": " Ready to learn Git?<\/p> \n Try this interactive tutorial.<\/p>", "cls": "related-post--text"} , { "tag": "A", "href": "/git/tutorials/learn-git-with-bitbucket-cloud", "text": "Get started now", "cls": "related-post--link button green-solid"} ] } ] }, "git/articles/ci-friendly-git-repos": { "meta": { "title": "Five tips for CI-friendly Git repos | Atlassian Git Tutorial", "description": "Atlassian Git Tutorial", "canonical": "https://www.atlassian.com/continuous-delivery/ci-friendly-git-repos"}, "topbar": { "text": "Articles", "cls": "articles", "href": "/git/articles" }, "flags": { "isSearch": false, "isTutorial": false }, "dom": [ { "tag": "DIV", "cls": " articles-header", "children": [ { "tag": "DIV", "cls": "g-column g-12-12 t-12-12 m-10-12 _header g-centered text-center", "children": [ { "tag": "H1", "text": "Five tips for CI-friendly Git repos", "cls": ""} , { "tag": "IMG", "src": "/dam/jcr:a70fc026-652a-43e9-89d0-8f753349d49a/sarah-goff-dupont.png", "alt": "Sarah Goff-Dupont", "cls": "_avatar"} , { "tag": "H6", "text": "Sarah Goff-Dupont", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " articles-content", "children": [ { "tag": "A", "href": "/git/articles", "text": "Back to list", "cls": "_back"} , { "tag": "DIV", "cls": "g-row container", "children": [ { "tag": "DIV", "cls": "g-column g-12-12 t-12-12 m-10-12 g-centered text-left", "children": [ { "tag": "DIV", "text": " If you follow Atlassian, you know we're big on continuous integration<\/a> ("CI") and Git–separately, sure: but even bigger on the power that the two offer in combination. Today I want to share some tips for getting your CI system to interact optimally with your repository, which is where it all begins.<\/p>", "cls": ""} , { "tag": "H2", "text": "1: Avoid tracking large files in your repo", "cls": ""} , { "tag": "DIV", "text": " One of the things you often hear about Git is that you should avoid putting large files into your repository: binaries, media files, archived artifacts, etc. This is because once you add a file, it will always be there in the repo’s history, which means every time the repo is cloned, that huge heavy file will be cloned along with it. And getting a file out of the repo’s history is very tricky, It’s the equivalent of performing a lobotomy on your code base. And this surgical file extraction alters the whole history of the repo, so you no longer have a clear picture of what changes were made and when. All good reasons to avoid large files as a general rule.<\/p>", "cls": ""} , { "tag": "DIV", "text": " But keeping large files out is especially important if you are doing CI.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Each time you build, your CI server has to clone your repo into the working build directory. And if your repo is bloated with a bunch of huge artifacts, it slows that process down and increases the time your developers have to wait for build results.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Ok, fine. But what if your build depends on binaries from other projects or large artifacts? That’s a very common situation, and probably always will be. So the question is: how can we handle it effectively?<\/p>", "cls": ""} , { "tag": "DIV", "text": " A storage system like Artifactory (who make an add-on for Bamboo), Nexus, or Archiva can help for artifacts that are generated by your team or the teams around you. The files you need can be pulled into the build directory at the beginning of your build–just like the 3rd-party libraries you pull in via Maven or Gradle.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Now you may be thinking “Oh, I’ll just sync my big files to the build server each night so I only have to transfer them across disk at build time.”<\/p>", "cls": ""} , { "tag": "DIV", "text": " Even though a disc transfer is much faster than network transfer, I actually recommend against doing this, especially if the artifacts change frequently. In between your nightly syncs, you’ll end up building with stale versions of the artifacts. Plus, developers need these files for builds on their local workstations anyway. So overall, the cleanest thing to do is to just make artifact download part of the build.<\/p>", "cls": ""} , { "tag": "H2", "text": "2: Use shallow clones for CI", "cls": ""} , { "tag": "DIV", "text": " Each time a build runs, your build server clones your repo into the current working directory. As I mentioned before, when Git clones a repo, it clones the repo’s entire history by default. So over time, this operation will naturally take longer and longer. Unless your CI system uses shallow clones.<\/p>", "cls": ""} , { "tag": "DIV", "text": " With shallow clones, only the current snapshot of your repo will be pulled down. So it can be quite useful for reducing build times, especially when working with large and/or older repositories.<\/p>", "cls": ""} , { "tag": "DIV", "text": " But let’s say your build requires the full repo history–if, for example, you have a release build that adds a tag or updates the version in your POM, or you’re merging two branches with each build.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Earlier versions of Git require the entire repo history to be present in order to push changes. As of 1.9, simple changes to files can be pushed without the entire history present. But merging still requires the full history because Git needs to look back and find the common ancestor of the two branches–that’s going to be a problem if your build uses shallow cloning. Which leads me to tip #3.<\/p>", "cls": ""} , { "tag": "H2", "text": "3: Cache the repo on build agents", "cls": ""} , { "tag": "DIV", "text": " This also makes the cloning operation much faster, and some CI servers actually do this by default.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Note that repo caching only benefits you if you are using agents that persist from build to build. If you create and destroy build agents on EC2 or another cloud provider every time a build runs, repo caching won’t matter because you’ll be working with an empty build directory and will have to pull down a full copy of the repo every time anyway.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Shallow clones plus repo caching, divided by persistent vs. elastic agents, equals an interesting web of factors. Here's a little matrix to help you get strategic about it.<\/p>", "cls": ""} , { "tag": "IMG", "src": "/dam/jcr:f10712eb-81d3-40ad-873a-0060987ac6ac/matrix2.png", "alt": "Matrix", "cls": ""} , { "tag": "H2", "text": "4: Choose your triggers wisely", "cls": ""} , { "tag": "DIV", "text": " It goes (almost) without saying that running CI on all your active branches is a good idea. But is it a good idea to run all builds on all branches against all commits? Probably not. Here's why.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Let's take Atlassian, for example. We have upwards of 500 developers, each pushing changes to the repo several times a day–mostly pushes to their feature branches. That's a lot of builds. And unless you scale your build agents instantly and infinitely, it means a lot of waiting in the queue.<\/p>", "cls": ""} , { "tag": "DIV", "text": " One of our internal Bamboo servers houses 935 different build plans. We plugged 141 build agents into this server, and used best practices like artifact passing and test parallelization to make each build as efficient as possible. And still: building each commit was clogging up the works.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Instead of simply setting up another Bamboo instance with another 100+ agents, we stepped back and asked if this was truly necessary. And the answer was no.<\/p>", "cls": ""} , { "tag": "DIV", "text": " We found that a good way to balance testing rigor with resource conservation is to make builds on the dev branches push-button. This is where most of the change activity is happening, so it’s the biggest opportunity for savings. Developers find that it fits naturally into their workflow, and they like the extra control and flexibility this gives them.<\/p>", "cls": ""} , { "tag": "DIV", "text": " For critical branches like master and stable release branches, builds are triggered automatically by polling the repo for changes. Since we use dev branches for all our work-in-progress, the only commits coming into master should (in theory) be dev branches getting merged in. Plus, these are the code lines we release from and make our dev branches from. So it’s really important that we get timely test results against every commit.<\/p>", "cls": ""} , { "tag": "H2", "text": "5: Stop polling, start hooking", "cls": ""} , { "tag": "DIV", "text": " Another option is move away from polling altogether, and have the repo call out to your CI server when a change has been pushed and needs to be built. Typically, this is done by way of a hook in your repository.<\/p>", "cls": ""} , { "tag": "DIV", "text": " You can do this with whatever tooling you've got, but as it happens, we recently added an integration between Bitbucket Server and Bamboo that makes this extra set-up unnecessary. Once Bamboo and Bitbucket Server are linked on the back end, repo-driven build triggers Just Work™ right out of the box. No hooks or special configs required.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Regardless of tooling, repo-driven triggers carry the advantage of automatically fading into the sunset when the target branch goes inactive. In other words, you'll never waste your CI system's CPU cycles polling hundreds of abandoned branches. Or waste your own time manually turning off branch builds. (Though it's worth noting that Bamboo can easily be configured to ignore branches after X days of inactivity, if you still prefer polling.)<\/p>", "cls": ""} , { "tag": "DIV", "text": " Rubber, meet road<\/p>", "cls": ""} , { "tag": "DIV", "text": " You can implement every tip I've given here with any CI server on the market. But since we're always looking to make best practices easy to practice, we've baked them all into Bamboo so they're dead-simple to set up. Hop into the tour<\/a> and check out all the goodness.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Ready to learn Git?<\/p> \n Try this interactive tutorial.<\/p>", "cls": "related-post--text"} , { "tag": "A", "href": "/git/tutorials/learn-git-with-bitbucket-cloud", "text": "Get started now", "cls": "related-post--link button green-solid"} ] } ] }, "git/articles/core-concept-workflows-and-tips": { "meta": { "title": "Core Concept, Workflows And Tips | Atlassian Git Tutorial", "description": "Atlassian Git Tutorial", "canonical": "https://www.atlassian.com/blog/git/git-submodules-workflows-tips"}, "topbar": { "text": "Articles", "cls": "articles", "href": "/git/articles" }, "flags": { "isSearch": false, "isTutorial": false }, "dom": [ { "tag": "DIV", "cls": " articles-header", "children": [ { "tag": "DIV", "cls": "g-column g-12-12 t-12-12 m-10-12 _header g-centered text-center", "children": [ { "tag": "H1", "text": "Core Concept, Workflows And Tips", "cls": ""} , { "tag": "IMG", "src": "/dam/jcr:1a355490-1c55-42a2-aa4a-30b260d0163e/nicola-paolucci.png", "alt": "Nicola Paolucci", "cls": "_avatar"} , { "tag": "H6", "text": "Nicola Paolucci", "cls": ""} ] } ] } , { "tag": "DIV", "cls": " articles-content", "children": [ { "tag": "A", "href": "/git/articles", "text": "Back to list", "cls": "_back"} , { "tag": "DIV", "cls": "g-row container", "children": [ { "tag": "DIV", "cls": "g-column g-12-12 t-12-12 m-10-12 g-centered text-left", "children": [ { "tag": "DIV", "text": " Including submodules as part of your Git development allows you to include other projects in your codebase, keeping their history separate but synchronized with yours. It's a convenient way to solve the vendor library and dependency problems. As usual with everything First, let me provide a brief explanation on a core concept about submodules that will make them easier to work with.<\/p>", "cls": ""} , { "tag": "DIV", "text": " Submodules are tracked by the exact commit<\/em> specified in the parent project, not a branch, a ref, or any other symbolic reference.<\/strong><\/p>", "cls": ""} , { "tag": "DIV", "text": " They are never<\/em> automatically updated when the repository specified by the submodule is updated, only when the parent project itself is updated. As very clearly expressed in the Pro Git chapter<\/a> mentioned earlier:<\/p>", "cls": ""} , { "tag": "DIV", "text": " When you make changes and commit in that [submodule] subdirectory, the superproject notices that the HEAD there has changed and records the exact commit you’re currently working off of; that way, when others clone this project, they can re-create the environment exactly.<\/p> \n<\/blockquote>", "cls": ""} , { "tag": "DIV", "text": " Or in other words<\/a> :<\/p>", "cls": ""} , { "tag": "DIV", "text": " [...] git submodules [...] are static. Very static. You are tracking specific commits with git submodules - not branches, not references, a single commit. If you add commits to a submodule, the parent project won't know. If you have a bunch of forks of a module, git submodules don't care. You have one remote repository, and you point to a single commit. Until you update the parent project, nothing changes.<\/p> \n<\/blockquote>", "cls": ""} , { "tag": "H2", "text": "Possible Workflows", "cls": ""} , { "tag": "DIV", "text": " By remembering this core concept and reflecting on it, you can understand that When a component or subproject is changing too fast or upcoming changes will break the API, you can lock the code to a specific commit for your own safety.<\/p><\/li> \n When you have a component that isn't updated very often and you want to track it as a vendor dependency. I do this for my vim plugins<\/a> for example.<\/p><\/li> \n When you are delegating a piece of the project to a third party and you want to integrate their work at a specific time or release. Again this works when updates are not too frequent.<\/p><\/li> \n<\/ul>", "cls": ""} , { "tag": "DIV", "text": " Credit<\/a> to finch<\/em> for the well-explained scenarios.<\/p>", "cls": ""} , { "tag": "H2", "text": "Useful Tips Incoming", "cls": ""} , { "tag": "DIV", "text": " The submodule<\/a> infrastructure is powerful and allows for useful separation and integration of codebases. There are however simple operations that do not have a streamlined procedure or strong command line user interface support.<\/p>", "cls": ""} , { "tag": "DIV", "text": " If you use git submodules in your project you either have run into these or you will. When that happens you will have to look the solution up. Again and again. Let me save you research time: Instapaper<\/a>, Evernote<\/a> or old school bookmark<\/a> this page (:D:D) and you will be set for a while.<\/p>", "cls": ""} , { "tag": "DIV", "text": "Five tips for CI-friendly Git repos<\/a><\/h1>\n", "cls": ""} , { "tag": "IMG", "src": "/dam/jcr:a70fc026-652a-43e9-89d0-8f753349d49a/sarah-goff-dupont.png", "alt": "Sarah Goff-Dupont", "cls": "_avatar"} , { "tag": "DIV", "text": "
forks<\/code><\/a> updated against the upstream<\/code> repositories (and if you're wondering why you would want to use forks in an enterprise setting, check out a few reasons here<\/a>). In this blog I will introduce you to few aspects of how forking interacts with upstream<\/code>: the basics, the gotcha's, and an cool tip. To top it off I will then make you very jealous, or very eager, the choice is yours. Interested? Read on.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/git-forks-and-upstreams", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "What's new in Git 2.1", "cls": ""} , { "tag": "DIV", "text": "git<\/code>, the approach is opinionated and encourages a bit of study before it can be used proficiently. There is already good<\/a> and detailed<\/a> information about submodules<\/code> out and about so I won't rehash things. What I'll do here is share some interesting things that will help you make the most of this feature.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/core-concept-workflows-and-tips", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Git team workflows: merge or rebase?", "cls": ""} , { "tag": "DIV", "text": "git<\/code><\/a> and feature branching<\/a>, what's the best way to incorporate finished work back to your main line of development? It's one of those recurring debates where both sides have strong opinions, and mindful conversation can sometimes be hard (for other examples of heated debate see: The Internet<\/a>).<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/git-team-workflows-merge-or-rebase", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "How to handle big repositories with git", "cls": ""} , { "tag": "DIV", "text": "git<\/code> is a fantastic choice for tracking the evolution of your code base and to collaborate efficiently with your peers. But what happens when the repository you want to track is really<\/strong> huge?<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/how-to-handle-big-repositories-with-git", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Alternatives To Git Submodule: Git Subtree", "cls": ""} , { "tag": "DIV", "text": "submodules<\/code> are useful for a few use cases but have several drawbacks.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/alternatives-to-git-submodule-git-subtree", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Extending git", "cls": ""} , { "tag": "DIV", "text": "git<\/code>? Our project is made up of multiple inter-dependent repositories. Currently we manage those with svn:externals<\/code>. What's the best way to handle those with git<\/code>? How do you split a very big repository in smaller components using git? These are some examples of the most asked questions we got at the European leg of our recent Getting Git Right<\/a> tour.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/git-and-project-dependencies", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Simple Git workflow is simple", "cls": ""} , { "tag": "DIV", "text": "git<\/code> and many more are transitioning to it now. Apart from training single developers and appointing Champions<\/strong> to help with the adoption it is imperative to pick a nice and simple code collaboration practice that does not complicate things too much. With git<\/code> one can definitely conjure very complicated workflows, I've seen them first hand.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/simple-git-workflow-is-simple", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Titanium Armor: Recovering From Various Disasters", "cls": ""} , { "tag": "DIV", "text": "git<\/code> workflows. Branching workflows go from bare and simple, to complex, robust, and defensive. What is the level of complexity and safeguard needed by your organization? This post covers the compromise between nimbleness and robustness, with some guidelines to choose your own git<\/code> adventure and lessons learned inside Atlassian.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/trust-the-merge-and-branch-simplification-musings", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "Use Git even if your team doesn't: git-svn tips and tricks", "cls": ""} , { "tag": "DIV", "text": "git<\/code> on the command line or via a tool of choice like SourceTree<\/a>; whether you host your code on Bitbucket Cloud<\/a> or on Stash<\/a> (now called Bitbucket Server) behind your company firewall, if you're like me - wink<\/em> - when a new git<\/code> release comes out it's always a party.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/what-you-need-to-know-about-the-new-git-1-8-3", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "What's new in Git 1.8.5", "cls": ""} , { "tag": "DIV", "text": "git<\/code> release which will bring about some serious updates let's peel off the notes of the latest point release: 1.8.5<\/code> is upon us!<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/whats-new-in-git-1-8-5", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "What's new in Git 1.9", "cls": ""} , { "tag": "DIV", "text": "git<\/code> point release (1.9<\/code>) has come out!<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/whats-new-in-git-1-9", "text": "Read full post", "cls": ""} ] } , { "tag": "DIV", "cls": "g-column g-4-12 t-6-12 m-12-12 articles-item text-left", "children": [ { "tag": "H5", "text": "It happened: Git 2.0 is here and it's full of goodies", "cls": ""} , { "tag": "DIV", "text": "git<\/code> has been brewing for a long time and I am excited to go on the hunt in the Changelog to find cool bits of awesomeness. As usual if you want to catch up with past git releases, I've been doing this exercise for a while, check them out: 1.8.2<\/a>, 1.8.3<\/a>, 1.8.4<\/a>, 1.8.5<\/a>, 1.9<\/a>.<\/p>\n", "cls": "_text-content"} , { "tag": "A", "href": "/git/articles/whats-new-in-git-2-1", "text": "Read full post", "cls": ""} ] } ] } ] }, "git/articles/10-years-of-git": { "meta": { "title": "10 Years of Git | Atlassian Git Tutorial", "description": "Learn how other developers are using Git. Tools, tips, tricks, best practices, and more.", "canonical": "https://www.atlassian.com/git/articles/10-years-of-git"}, "topbar": { "text": "Articles", "cls": "articles", "href": "/git/articles" }, "flags": { "isSearch": false, "isTutorial": false }, "dom": [ { "tag": "DIV", "cls": " ten-years-index", "children": [ { "tag": "DIV", "cls": " _header", "children": [ { "tag": "DIV", "cls": " _header-content", "children": [ { "tag": "H1", "text": "10 years of Git", "cls": ""} , { "tag": "IMG", "src": "/dam/jcr:ffd56b30-ad4d-4cb5-94be-79c1dd68b1fb/Atlassian-horizontal-white-rgb.svg", "alt": "Atlassian", "href": "/", "cls": ""} , { "tag": "DIV", "cls": " social", "children": [ { "tag": "A", "href": "https://twitter.com/home?status=10%20years%20of%20Git.%20http%3A%2F%2Fatlassian.com%2Fgit%2Farticles%2F10-years-of-git", "text": "Twitter", "cls": "icon-footer-twitter"} , { "tag": "A", "href": "https://www.facebook.com/sharer/sharer.php?u=http://www.atlassian.com/git/articles/10-years-of-git", "text": "Facebook", "cls": "icon-footer-facebook"} ] } ] } , { "tag": "DIV", "cls": " _hero", "children": [ { "tag": "IMG", "src": "/dam/jcr:f52723db-1107-4775-8a47-510abca7728a/new-hero-02.svg", "cls": "svg"} ] } ] } , { "tag": "DIV", "cls": " container", "children": [ { "tag": "DIV", "cls": " container-inner", "children": [ { "tag": "DIV", "text": "\n\t
submodules<\/code> are useful for a few use cases but have several drawbacks.<\/p>\n", "cls": ""} , { "tag": "DIV", "text": " \n
git subtree<\/code> and show why it is an improvement - albeit not perfect - over git submodule<\/code>.<\/p>", "cls": ""} , { "tag": "DIV", "text": "subtree<\/code> better to use:<\/p>", "cls": ""} , { "tag": "DIV", "text": " \n
git<\/code> are supported (even before v1.5.2<\/code>).<\/li> \n clone<\/code> of the super project is done.<\/li> \n subtree<\/code> does not require users of your repository to learn anything new, they can ignore the fact that you are using subtree<\/code> to manage dependencies.<\/li> \n subtree<\/code> does not add new metadata files like submodules<\/code> doe (i.e. .gitmodule<\/code>).<\/li> \n \n
subtree<\/code>).<\/li> \n upstream<\/code> for the sub-projects is slightly more complicated.<\/li> \n git subtree<\/code> is available in stock version of git<\/code> available since May 2012 – 1.7.11<\/code>+. The version installed by homebrew<\/a> on OSX already has subtree properly wired but on some platforms you might need to follow the installation instructions<\/a>.<\/p>", "cls": ""} , { "tag": "DIV", "text": "git subtree<\/code>. <\/p>", "cls": ""} , { "tag": "H3", "text": "The quick and dirty way without remote tracking", "cls": ""} , { "tag": "DIV", "text": "subtree<\/code> at a specified prefix<\/code> folder:<\/p>", "cls": ""} , { "tag": "DIV", "text": "git subtree add --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git master --squash<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "--squash<\/code> flag.)<\/em><\/p>", "cls": ""} , { "tag": "DIV", "text": "git fetch https://bitbucket.org/vim-plugins-mirror/vim-surround.git master\nwarning: no common commits\nremote: Counting objects: 338, done.\nremote: Compressing objects: 100% (145/145), done.\nremote: Total 338 (delta 101), reused 323 (delta 89)\nReceiving objects: 100% (338/338), 71.46 KiB, done.\nResolving deltas: 100% (101/101), done.\nFrom https://bitbucket.org/vim-plugins-mirror/vim-surround.git\n* branch master -} FETCH_HEAD\nAdded dir '.vim/bundle/tpope-vim-surround'<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "merge commit<\/code> by squashing the whole history of the vim-surround<\/code> repository into a single one:<\/p>", "cls": ""} , { "tag": "DIV", "text": "1bda0bd [3 minutes ago] (HEAD, stree) Merge commit 'ca1f4da9f0b93346bba9a430c889a95f75dc0a83' as '.vim/bundle/tpope-vim-surround' [Nicola Paolucci]\nca1f4da [3 minutes ago] Squashed '.vim/bundle/tpope-vim-surround/' content from commit 02199ea [Nicola Paolucci]<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "upstream<\/code> repository you can just subtree pull<\/code>:<\/p>", "cls": ""} , { "tag": "DIV", "text": "git subtree pull --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git master --squash<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "git subtree add --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround master --squash<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "git fetch tpope-vim-surround master\ngit subtree pull --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround master --squash<\/code><\/pre>", "cls": ""} , { "tag": "H3", "text": "Contributing back to upstream", "cls": ""} , { "tag": "DIV", "text": "upstream<\/code> project we need to fork the project and add it as another remote:<\/p>", "cls": ""} , { "tag": "DIV", "text": "git remote add durdn-vim-surround ssh://git@bitbucket.org/durdn/vim-surround.git<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "subtree push<\/code> command like the following:<\/p>", "cls": ""} , { "tag": "DIV", "text": "git subtree push --prefix=.vim/bundle/tpope-vim-surround/ durdn-vim-surround master\n\ngit push using: durdn-vim-surround master\nCounting objects: 5, done.\nDelta compression using up to 4 threads.\nCompressing objects: 100% (3/3), done.\nWriting objects: 100% (3/3), 308 bytes, done.\nTotal 3 (delta 2), reused 0 (delta 0)\nTo ssh://git@bitbucket.org/durdn/vim-surround.git\n 02199ea..dcacd4b dcacd4b21fe51c9b5824370b3b224c440b3470cb -} master<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "pull-request<\/code> to the maintainer of the package.<\/p>", "cls": ""} , { "tag": "H3", "text": "Without using the subtree command", "cls": ""} , { "tag": "DIV", "text": "git subtree<\/code> is different from the subtree merge strategy<\/a>. You can still use the merge strategy even if for some reason git subtree<\/code> is not available. Here is how you would go about it:<\/p>", "cls": ""} , { "tag": "DIV", "text": "git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "git merge -s ours --no-commit tpope-vim-surround/master<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "Automatic merge went well; stopped before committing as requested<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "git read-tree --prefix=.vim/bundle/tpope-vim-surround/ -u tpope-vim-surround/master<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "git ci -m"[subtree] adding tpope-vim-surround"\n\n[stree 779b094] [subtree] adding tpope-vim-surround<\/code><\/pre>", "cls": ""} , { "tag": "DIV", "text": "pull<\/code> using the subtree<\/code> merge strategy:<\/p>", "cls": ""} , { "tag": "DIV", "text": "git pull -s subtree tpope-vim-surround master<\/code><\/pre>", "cls": ""} , { "tag": "H2", "text": "Conclusions", "cls": ""} , { "tag": "DIV", "text": "submodule<\/code> for a while I appreciate git subtree<\/code> much more, lots of submodule<\/code> problems are superseded and solved by subtree<\/code>. As usual, with all things git<\/code>, there is a learning curve to make the most of the feature.<\/p>", "cls": ""} , { "tag": "DIV", "text": "Share this<\/h6> \n Twitter<\/a>\n<\/div>", "cls": "_footer"} ] } ] } ] } , { "tag": "DIV", "id": "related-post-sidebar", "cls": " related-post", "children": [ { "tag": "DIV", "text": "
Share this<\/h6> \n Twitter<\/a>\n<\/div>", "cls": "_footer"} ] } ] } ] } , { "tag": "DIV", "id": "related-post-sidebar", "cls": " related-post", "children": [ { "tag": "DIV", "text": "
git<\/code>, the approach is opinionated and encourages a bit of study before it can be used proficiently. There is already good<\/a> and detailed<\/a> information about submodules<\/code> out and about so I won't rehash things. What I'll do here is share some interesting things that will help you make the most of this feature.<\/p>", "cls": ""} , { "tag": "H2", "text": "Table Of Contents", "cls": ""} , { "tag": "DIV", "text": " \n
\n
\n
submodule<\/code> support some workflows well and less optimally others. There are at least three scenarios where submodules are a fair choice:<\/p>", "cls": ""} , { "tag": "DIV", "text": " \n