{"id":606594,"date":"2023-02-10T07:48:50","date_gmt":"2023-02-10T13:48:50","guid":{"rendered":"https:\/\/news.sellorbuyhomefast.com\/index.php\/2023\/02\/10\/trunk-based-development-game-changers\/"},"modified":"2023-02-10T07:48:50","modified_gmt":"2023-02-10T13:48:50","slug":"trunk-based-development-game-changers","status":"publish","type":"post","link":"https:\/\/newsycanuse.com\/index.php\/2023\/02\/10\/trunk-based-development-game-changers\/","title":{"rendered":"Trunk-Based Development: Game Changers"},"content":{"rendered":"<div>\n<h2><span>Game Changers <\/span><\/h2>\n<p>Since the early 80\u2019s a number of things have pushed best practices <strong>towards<\/strong> Trunk-Based Development, or <strong>away<\/strong> from it.<\/p>\n<p>The language in use to describe such things has changed over time. Software Configuration Management (SCM) is used less<br \/>\ntoday than Version Control Systems (VCS) is. A simpler still term &#8211; \u201cSource Control\u201d &#8211; seems to be used more recently,<br \/>\ntoo.<\/p>\n<p>Similarly, \u2018trunk\u2019 and \u2018branch\u2019, have not always been used as terms for controlled code lines that have a common<br \/>\nancestor, and are eminently (and repeatably) mergeable.<\/p>\n<h2 id=\"revision-control-system---rcs-1982\">Revision Control System &#8211; RCS (1982)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd1.png\" alt><\/p>\n<p>RCS was a simple but \u2018early days\u2019 version control technology, by Walter F. Tichy.<\/p>\n<p>In Tichy\u2019s 1985 paper<br \/>\n\u201cRCS &#8211; A System for Version Control&#8221;<span><a target=\"_blank\" href=\"https:\/\/www.gnu.org\/software\/rcs\/tichy-paper.pdf\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>, a trunk<br \/>\nfocused mode of use is described as a \u201cslender branch\u201d. In section 3.1. \u201cWhen are branches needed?\u201d,<br \/>\nhe says that you step away from the trunk for four reasons:<\/p>\n<p>Two of those, Tichy suggests, are temporary branches and would come back to the trunk at the earliest opportunity.<\/p>\n<p>Superficially, RCS allowed multi-branch parallel development, but some teams were very careful and stuck<br \/>\nto a \u2018slender\u2019, or Trunk-Based Development mode of use.<\/p>\n<p>Note: Over time all version control systems would adopt this branch\/merge language.<\/p>\n<h2 id=\"concurrent-versions-system---cvs-1990\">Concurrent Versions System &#8211; CVS (1990)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd1.png\" alt><\/p>\n<p>A handful of scripts created in 1986 by Dick Grune, were fashioned into an initial release of CVS<span><a target=\"_blank\" href=\"https:\/\/en.wikipedia.org\/wiki\/Concurrent_Versions_System\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span><br \/>\nin 1990. For the open source community, CVS was it until Subversion came along years later. The adoption of CVS in the<br \/>\nyoung open source community spurred its adoption in the enterprise too. While many branching models were possible,<br \/>\nmerging was painful and Trunk-Based Development was the sensible choice. Indeed CVS popularized the \u201ctrunk\u201d branch name, even if it didn\u2019t mandate it.  CVS\u2019s flaws were that it did not have atomic commits, its operation over the wire as a centralized client\/server VCS was very chatty, and it had cumbersome CVS\/ directories all over the checked out code.<\/p>\n<h2 id=\"microsoft-secrets-book-1995\">Microsoft Secrets book (1995)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd3.png\" alt><\/p>\n<p>Microsoft Secrets: How the World\u2019s Most Powerful Software Company Creates Technology, Shapes Markets and Manages<br \/>\nPeople (Michael Cusumano &#038; Richard Selby, 1995)<span><a target=\"_blank\" href=\"https:\/\/www.amazon.com\/Microsoft-Secrets-Powerful-Software-Technology\/dp\/0684855313\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span><\/p>\n<p>The book was translated into 14 languages, and a bestseller, and was about practices that solidified within Microsoft<br \/>\nfor a few years before.<\/p>\n<p>There\u2019s a section in <em>Microsoft Secrets<\/em> dealing with Microsoft\u2019s per-developer workflow using Source Library Manager<br \/>\n(SLM) on  a one-branch model (the book does not use the words trunk or branch). SLM (AKA \u201cslime\u201d) &#8211; was an internal<br \/>\ntool Microsoft used for source-control. The <em>daily<\/em> developer workflow with SLM was:<\/p>\n<ol>\n<li>checkout (update\/pull\/sync or checkout afresh)<\/li>\n<li>implement feature<\/li>\n<li>build<\/li>\n<li>test the feature<\/li>\n<li>sync (update\/pull)<\/li>\n<li>merge<\/li>\n<li>build<\/li>\n<li>test the feature<\/li>\n<li>smoke tests<\/li>\n<li>check in (commit\/push)<\/li>\n<li>makes a daily build from HEAD of the shared main branch<\/li>\n<\/ol>\n<p>The authors note in the book, that #10 is not always an everyday thing. And the last step, #11, is not per developer, it is<br \/>\nfor the designated \u201cbuildmeister\u201d within the team, and manual. This workflow was initially pioneered in the Excel group,<br \/>\nand then Word, and then Windows NT, and the timespan for this way of working was from around 1989 through 1995 when the<br \/>\ninterviews completed and the book published.<\/p>\n<p>The book also briefly mentions Test Case Manager (TCM) and \u201cMicrosoft Test\u201d. These were tools for helping developers<br \/>\nmanage and record\/edit\/playback application tests at their workstations. It is not clear if all SLM-using teams<br \/>\nalso used these, but the Excel team did (as they maintained the former at least).<\/p>\n<p>These are clearly practices to support teams working in a trunk model.<\/p>\n<p>Notes:<\/p>\n<ol>\n<li>\n<p>Steve McConnell\u2019s Rapid Development (1996) also reinforces #11 &#8211; make a daily build.<\/p>\n<\/li>\n<li>\n<p>In 2000, ex Microsoftee and early blogger Joel Spolsky would extol the virtues of #11 in his famous<br \/>\n\u201cThe Joel Test&#8221;<span><a target=\"_blank\" href=\"https:\/\/www.joelonsoftware.com\/2000\/08\/09\/the-joel-test-12-steps-to-better-code\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> posting.<\/p>\n<\/li>\n<\/ol>\n<h2 id=\"netscapes-tinderbox-1997\">NetScape\u2019s Tinderbox (1997)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd1.png\" alt><\/p>\n<p>NetScape (now Mozilla) had a service that compiled and tested bits and pieces of their open-source offerings together. That service was<br \/>\nTinderbox and it debuted for the public to see in 1997. Their source organization was single-branch in the trunk style<br \/>\nmanaged by CVS, and allowed individual developers to checkout and keep abreast of only the pieces they wanted\/needed to. Tinderbox<br \/>\nwas the safety net that ensured everything was correct across all the whole trunk. It ran until it wouldn\u2019t scale anymore<br \/>\nin 2014<span><a target=\"_blank\" href=\"http:\/\/oduinn.com\/blog\/2014\/06\/04\/farewell-to-tinderbox\/\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<\/p>\n<h2 id=\"perforce-and-clearcase-1998\">Perforce and ClearCase (1998)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/away_from_tbd3.png\" alt><\/p>\n<p>Perforce and ClearCase bit into the corporate VCS market significantly. Both, as technologies, were<br \/>\nopen to any branching model and implementing teams chose differently. In the end, though, people\u2019s newfound willingness<br \/>\nto experiment with multiple parallel active branches won out, and we had some dark years generally for Trunk-Based<br \/>\nDevelopment ahead, even if branch names sometimes included \u2018trunk\u2019. Both Perforce and ClearCase has decent merge<br \/>\ntracking, but Perforce was much faster on the wire.<\/p>\n<p>Microsoft installed a custom build of Perforce called \u201cSource Depot\u201d. It took over from SLM\/Slime (mentioned above).<br \/>\nWe are not sure, but Microsoft may have embraced the possibility of multiple active branches (rather than<br \/>\nTrunk-Based Development) back then within their Source Depot (SD) setup.<\/p>\n<p>By contrast, Google installed Perforce (see below) and embraced a Trunk-Based Development model with it from the outset.<br \/>\nThey rose to every scaling challenge with extra tooling around it, including more than a few actual inventions of<br \/>\ntechnology and technique (see below).<\/p>\n<h3 id=\"perforces-high-level-scm-best-practices-white-paper\">Perforce\u2019s High-Level SCM Best Practices white paper<\/h3>\n<p>Laura Wingerd and Christopher Seiwald penned this widely read paper<span><a target=\"_blank\" href=\"https:\/\/www.perforce.com\/sites\/default\/files\/pdf\/perforce-best-practices.pdf\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span><br \/>\nthat was presented at an SCM conference in Brussels the same year.<\/p>\n<p>The paper alternates between \u2018trunk\u2019 and \u2018mainline\u2019 language, but has many valuable nuggets in<br \/>\nit that help set a foundation for the next ten years of version-control advances.<\/p>\n<h2 id=\"extreme-programmings-continuous-integration-1999\">Extreme Programming\u2019s Continuous Integration (1999)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd3.png\" alt><\/p>\n<p>Kent Beck<span><a target=\"_blank\" href=\"https:\/\/en.wikipedia.org\/wiki\/Kent_Beck\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> published \u201cExtreme Programming Explained\u201d in 1999.<br \/>\nPicked out that, amongst a bunch of practices for the influential XP methodology, is \u201cContinuous Integration\u201d<br \/>\nthat Kent felt was \u201crisk reducing\u201d.<\/p>\n<p>He says \u201cIntegrate and build the system many times a day, every time a task is completed\u201d, and goes on to detail<br \/>\na reserved workstation, that a developer pair would sidle up at the appropriate moment to prove that their code<br \/>\ncontribution was integrateable, and therefore good for teammates to depend on at that moment. That last notification<br \/>\nwas often oral at that time \u201cbuild passes, gang\u201d.<\/p>\n<p>He calls out a requirement for \u201cfast integration\/build\/test cycles\u201d. This is key. In fact, every pro Trunk-Based Development<br \/>\ngame changer listed in this page was facilitated by faster builds generally (versus a predecessor technique for the team<br \/>\nin question). And, no, faster did not mean delete or comment out automated test execution in the build. Faster meant to reduce<br \/>\nthe elapsed time to \u201ca few minutes\u201d (Kent again).<\/p>\n<p>Kent had pioneered (with many industry luminary friends) in 1996 on the famous Chrysler Comprehensive Compensation System<br \/>\n(C3) project. The C3 project used Smalltalk as its language, and OTI\u2019s ENVY was the version control tool used. It is<br \/>\nimportant to note that today\u2019s CR-delimited text file systems are blunt instruments compared to the fine-grained<br \/>\ndirected graphs with fidelity down to class\/method history of each of those. It was more like a multidimensional<br \/>\ndatabase with cross-cutting tags representing HEAD, or someone else\u2019s important combination of those three. It was<br \/>\nomnipresent too &#8211; a decision made to move HEAD was instantly available without \u2018update\u2019 action to teammates.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd3.png\" alt><\/p>\n<p>Martin Fowler and Matt Foemmel<span><a target=\"_blank\" href=\"http:\/\/blog.foemmel.com\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> wrote an influential article \u201cContinuous<br \/>\nIntegration\u201d in 2000<span><a target=\"_blank\" href=\"https:\/\/www.martinfowler.com\/articles\/originalContinuousIntegration.html\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>,<br \/>\ncalling out this one part of XP. Martin greatly updated it in 2006<br \/>\n<span><a target=\"_blank\" href=\"https:\/\/www.martinfowler.com\/articles\/continuousIntegration.html\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<\/p>\n<h2 id=\"thoughtworks-cruise-control-2001\">ThoughtWorks&#8217; Cruise Control (2001)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd3.png\" alt><\/p>\n<p>Martin\u2019s ThoughtWorks colleagues (Alden Almagro<span><a target=\"_blank\" href=\"http:\/\/aldenalmagro.com\/resume.html\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>,<br \/>\nPaul Julius<span><a target=\"_blank\" href=\"http:\/\/www.pauljulius.com\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>,<br \/>\nJason Yip<span><a target=\"_blank\" href=\"http:\/\/jchyip.blogspot.com\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>) went on to build the then-dominant<br \/>\n\u201cCruise Control&#8221;<span><a target=\"_blank\" href=\"http:\/\/cruisecontrol.sourceforge.net\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> starting in early 2001 (for CVS, StarTeam). This was a<br \/>\ngroundbreaking technology and very accessible to companies wanting a machine to fully verify checkins. ThoughtWorks<br \/>\nalready had success the year before with the same server design on a client project, and CruiseControl was the<br \/>\nrewrite (from scratch) in order to make it open source. CruiseControl was quite successful in the enterprise and was<br \/>\nand easy decision after teams had read the Continuous Integration paper above.<\/p>\n<p>Early CI servers, including CruiseControl used to have a \u201cquiet period\u201d to make sure they had received every last<br \/>\nelement of an intended commit. To facilitate that, only one pair of developers was allowed to checkin at a time. With<br \/>\nCVS the other developers in the team could only do their \u201ccvs up\u201d when CruiseControl had given the green light,<br \/>\nautomating that \u201cbuild passes, gang\u201d oral notification above. A particular non-functional feature to note for<br \/>\nCruiseControl was that it stored its \u2018pipeline\u2019 configuration in source-control. In fact, that was alongside the<br \/>\nproject\u2019s source and build file &#8211; developers could tweak CI configuration in a commit.<\/p>\n<h2 id=\"apaches-gump\">Apache\u2019s Gump<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd1.png\" alt><\/p>\n<p>Apache\u2019s Gump was built on a similar timeline to CruiseControl but focused more on the binary integration hell of<br \/>\ninterdependent Apache (and other) open-source projects. It gave an early warning of integration clashes that were<br \/>\nalready or were about to be problematic, for teams. While impressive, it did not gain traction in the enterprise.<br \/>\nThis is because enterprises were able to be more buffered from open-source library hell (and the implicit diamond<br \/>\ndependency problem), by limiting the rate at which they upgraded their third-party binary dependencies.<\/p>\n<p>Gump creator, Sam Ruby remembers:<\/p>\n<h2 id=\"subversions-lightweight-branching-2000-through-2001\">Subversion\u2019s \u201clightweight\u201d branching (2000 through 2001)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/away_from_tbd1.png\" alt><\/p>\n<p>Karl Fogel helped start Subversion and remembers one early goal was \u201cCVS + atomicity\u201d. <strong>The lack of atomicity in CVS<br \/>\nmeant that teams had to coordinate as to who was checking in at any one time<\/strong> and whether they would avoid<br \/>\naccidentally breaking the build as a result. Early CI servers (as mentioned) used to have a \u201cquiet period\u201d<br \/>\nto make sure they had received every last element of an<br \/>\nintended commit, and that was no longer needed for Subversion and its atomic commits.<\/p>\n<p>In comparison to the clunky CVS, Subversion had \u201clightweight\u201d branching. This made it easier to consider multiple<br \/>\nbranches active in parallel and merge the team\u2019s changes back later.<\/p>\n<p>Until v1.5 in June 2008, Subversion had an inadequate \u201cmerge tracking\u201d capability, eliminating a class of problems<br \/>\ninherent in branching and merging. The internal mechanism of noting the merge tracking was controversial though, and<br \/>\nSubversion still has edge-case merge bugs today. Like this one<span><a target=\"_blank\" href=\"https:\/\/issues.apache.org\/jira\/browse\/SVN-4635\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<\/p>\n<p>Subversion by default setup a branch called trunk. That said, it allows any branching model to be used.<\/p>\n<h2 id=\"gits-lightweight-branching-2005\">Git\u2019s \u201clightweight\u201d branching (2005)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/away_from_tbd3.png\" alt><\/p>\n<p>In comparison to the clunky Subversion, Git had \u201clightweight\u201d branching.<br \/>\nThis made it easier to consider multiple branches as active (in parallel) and merged back later. Git\u2019s merge engine<br \/>\nwas very good too, and had merge tracking from the start. It was more able than prior merge technologies to<br \/>\nsilently process complexity.<\/p>\n<p>A critical part of Git was local branching. A developer could make multiple local branches, and even map them to the<br \/>\nsame remote branch. Say one could be a feature, part complete and another a surprise bug fix to go back first. Or the<br \/>\ndeveloper could be making alternate implementations of the same complicated thing, to decide later which to push back.<br \/>\nGit does not need a centralized server repo, but enterprise teams are going to have one anyway.<\/p>\n<p>Lastly, Git came with a capability to rewrite history. Although this was a general feature, it is where the history<br \/>\naround your local HEAD is rewritten before you push it back to the shared repository, that is of interest. Say your<br \/>\nAgile story was four tasks and there for four local commits, you can effectively squash those into one commit<br \/>\nbefore you push it back to the shared repository. There are pros and cons to that, but having the choice is cool.<\/p>\n<p>Generally, Git made it much easier to consider multiple branches as a viable team setup.<\/p>\n<h2 id=\"googles-internal-devops-2006-onwards\">Google\u2019s internal DevOps (2006 onwards)<\/h2>\n<p>Google\u2019s DevOps quest started in 1998, but was only really shared externally from 2006 onwards.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd3_but_secret.png\" alt><\/p>\n<p>Note: Google were practicing Trunk-Based Development since the beginning &#8211; Craig Silverstein (the first hire) remembers<br \/>\nsetting it up that way. Much of these were secret to Google until much later, including their recommendations for a<br \/>\n70:20:10 ratio for small:medium:large tests, where \u2018small\u2019 were sub-1ms unit tests (no threading, no I\/O), \u2018medium\u2019<br \/>\nwere unit tests that didn\u2019t qualify for <em>small<\/em> (and probably did TCP\/IP headlessly to something), with \u2018large\u2019 being<br \/>\nslower more costly Selenium functional tests. Pyramid like, and in the early to mid-2000\u2019s.<\/p>\n<h3 id=\"home-grown-ci-and-tooling\">Home-grown CI and tooling<\/h3>\n<p>This was 2002 onwards, but only barely documented outside Google, thus the influence is much smaller.<\/p>\n<p>Google is the most famous example of using Scaled CI infrastructure to keep up with commits (one every 30 seconds on<br \/>\naverage) to a single shared trunk. Google\u2019s setup would also allow the same infrastructure to verify <em>proposed<\/em> commits.<\/p>\n<p>Their VCS technology, at the outset, was Perforce, and it did not have an ability<br \/>\nto effectively do CI on commits that had not yet landed in the trunk. So Google made their own tooling for this and<br \/>\npending commits were plucked from developer workstations for verification (and code review &#8211; see \u201cMondrian\u201d below).<br \/>\nAfter its initial creation, Google\u2019s now \u201cGoogle3\u201d setup, gained a UI, Mondrian (see below)<br \/>\nwhich made the results of the pre-commit CI verification very clear.<\/p>\n<h3 id=\"mondrian-2006\">Mondrian (2006)<\/h3>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd3.png\" alt><\/p>\n<p>Tools for code-reviewers\/approvers of proposed contributions to trunk were developed internally at Google in the early<br \/>\n2000\u2019s as a command-line tool and part of \u201cGoogle 3\u201d. Things would not land in the shared trunk until everyone agreed.<br \/>\nTheir culture was that such that reviews were speedy. Getting pending commits to the point of rejection or acceptance<br \/>\n(\u201cLooks Good To Me\u201d: LGTM) was almost competitive. Some new Googlers (Nooglers) would pride themselves about taking<br \/>\non random code-review chores and being one of a few people that weigh into the decision moment.<\/p>\n<p>The code review technology marshaled changes for proposed commits to the trunk and stored them outside the VCS in<br \/>\nquestion (in a database probably). To do that the tech would reach into the developer machine at the appropriate<br \/>\nmoment and make a tar.gz of the changes and the meta-data around them, and pull that back to the central system<br \/>\nfor global presentation. Anyone could review anything. A review was just on a commit (not a batch of commits). Therefore<br \/>\ncode review was continuous.<\/p>\n<p>Reviewers could quickly bring the<br \/>\nmarshaled change down to their workstation to play with it, or use it as a basis for a counter proposal. They could put<br \/>\nthat back in review again.<\/p>\n<p>In 2006, Guido van Rossum presented one of his bigger contributions &#8211; \u201cMondrian\u201d &#8211;<br \/>\nto Googlers. Here is that \u2018tech talk\u2019 on YouTube:<\/p>\n<p>Note at the start he says XP practice<br \/>\n\u201cPair-Programming\u201d is best, and that code review helps fill the gap for situations where you cannot do it.<\/p>\n<p>See Rietveld and Gerrit further on, for continuations of the Mondrian story.<\/p>\n<h3 id=\"selenium-farm-2006\">Selenium Farm (2006)<\/h3>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd2.png\" alt><\/p>\n<p>Google CI infrastructure was expanded to have <strong>a second tier of elastic infrastructure<\/strong>, for scaled Selenium\/WebDriver<br \/>\ntesting.<\/p>\n<p>This \u201cSelenium Farm\u201d (internal cloud) was also available to developers at their desks, who just wanted to run such tests against a stood-up<br \/>\nversion of what they were working on. Teams who had to run Firefox (etc) on their own desktop on a Friday, were able<br \/>\nto lease one or more Firefox browsers  in parallel on a Monday, and no longer lock up their developer workstations.<\/p>\n<p>Other companies since have been able to deploy their own Selenium-Grid internally or<br \/>\nleverage one of the online services for elastic Selenium testing.<\/p>\n<h2 id=\"branch-by-abstraction-technique-2007\">Branch by Abstraction technique (2007)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd3.png\" alt><\/p>\n<p>Paul Hammant blogged about a 2005 ThoughtWorks client engagement in a Bank of America software development team,<br \/>\nthat used the Branch by Abstraction technique<span><a target=\"_blank\" href=\"http:\/\/paulhammant.com\/blog\/branch_by_abstraction.html\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<br \/>\nWhereas many had previously used this technique to avoid longer version-control branches in a trunk model, this was the<br \/>\nfirst time it had been detailed online and given a name (by Stacy Curl).<\/p>\n<h2 id=\"githubs-entire-initial-platform-2008\">GitHub\u2019s entire initial platform (2008)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/away_from_tbd2.png\" alt><\/p>\n<p>GitHub was launched as a portal on February 8, 2008, and features have been added steadily ever since. The initial<br \/>\nversion contained forks, which was a formal way of expressing the directionality of related DVCS repositories, and<br \/>\npromoting a forgiveness model for unsolicited changes to source code (as opposed to the permission model that preceded it<br \/>\nfor other portals).<\/p>\n<h3 id=\"pull-requests-2008\">Pull Requests (2008)<\/h3>\n<p>GitHub added \u201cPull-Requests\u201d (PRs) on Feb 23rd, 2008<span><a target=\"_blank\" href=\"https:\/\/github.com\/blog\/3-oh-yeah-there-s-pull-requests-now\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>,<br \/>\nwhile in beta, and popularized the entire practice for the industry when they came out of beta in April of that year.<br \/>\nFor source\/repo platforms, and VCSs generally, this and \u201cforking generally\u201d was a total game changer, and commercial<br \/>\nprospects of other companies were decided based on their ability to react to this culture change.<\/p>\n<h4 id=\"code-review-built-in\">Code Review built in<\/h4>\n<p>Pull Requests came with an ability to leave code review comments for the contribution. That meant that \u201cupstream\u201d<br \/>\nreceivers of contributions could parry them with feedback, rather than consume them and fix them which was common<br \/>\npreviously.<\/p>\n<h4 id=\"no-more-clunky-patch-sets\">No more clunky patch sets<\/h4>\n<p>GitHub\u2019s PR system used real branches in Git, and the forks aspect took advantage of the \u2018D\u2019 distributed in DVCS<br \/>\n(albeit distributed to somewhere else in GitHub\u2019s server-side directory structure).<\/p>\n<p>The open-source community for one could now step away from patch-sets that were donated by email (or other rudimentary mechanisms).<br \/>\nThis forced the entire VCS industry to take note, and plan equivalents, or commit to withering in terms of market<br \/>\nshare. It greatly facilitated multi-branch development for teams of course, including (sadly) multiple long-lived<br \/>\nbranches.<\/p>\n<p>Pull-Requests changed the dynamics of open source. Now, the original creator of open source was forced to keep up<br \/>\nwith PRs because if they did not, one fork with more activity and forward momentum, might steal the community. Perhaps<br \/>\nrightfully so.<\/p>\n<h4 id=\"timing\">Timing<\/h4>\n<p>In terms of timing GitHub\u2019s PR-centric code review was available for open-source use a couple of months before<br \/>\nGoogle\u2019s Rietveld was released, but a 18 months or so after Mondrian was presented in a tech talk that was put out on<br \/>\nvideo.google.com.  A few years later Google turned off video.google.com and moved the Mondrian tech-talk video to Youtube<br \/>\nwith its 2006 heritage being a mere note in the \u201cPublished on Aug 22, 2012\u201d posting.<\/p>\n<h3 id=\"rietveld-code-review-2008\">Rietveld code Review (2008)<\/h3>\n<p>After Mondrian and while at Google, Guido released Rietveld<span><a target=\"_blank\" href=\"https:\/\/github.com\/rietveld-codereview\/rietveld\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span><br \/>\nin its image (May, 2008) and a fork of that the Gerrit<span><a target=\"_blank\" href=\"https:\/\/www.gerritcodereview.com\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> (Oct, 2008) gained a lot of<br \/>\ninterest. Facebookers went on to make a similar Phabricator<span><a target=\"_blank\" href=\"https:\/\/en.wikipedia.org\/wiki\/Phabricator\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span><br \/>\nand released that as open source too (Oct, 2010).<\/p>\n<h2 id=\"continuous-delivery-book-2010\">Continuous Delivery Book (2010)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd2.png\" alt><\/p>\n<p>See <a href=\"https:\/\/trunkbaseddevelopment.com\/publications\/index.html#continuous-delivery-july-27-2010\">Publications &#8211; Continuous Delivery<\/a><\/p>\n<p>Jez Humble<span><a target=\"_blank\" href=\"https:\/\/continuousdelivery.com\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> and Dave<br \/>\nFarley<span><a target=\"_blank\" href=\"http:\/\/www.continuous-delivery.co.uk\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> wrote this influential book after a<br \/>\nThoughtWorks project in London that finished in 2007.<br \/>\nThe client was AOL &#8211; enough time has passed to share that. Specific DevOps advances were<br \/>\nbeing made across the industry, but a critical aspect of this mission was that the prescribed go-live date was tight, given the known<br \/>\namount of work to be completed before then. Tight enough to want to compress the classic \u2018coding slows down, and<br \/>\nexhaustive user acceptance testing starts\u2019 phase of a project. The team had to pull the trigger on plenty of<br \/>\nautomated steps, to allow faster feedback loops. This allowed then to have a high confidence in the quality of commits, from only<br \/>\nminutes before. CI pipelines and delta-scripts for database table-shape migrations, in particular, were focused on.<\/p>\n<p>The 2010 \u2018Continuous Delivery\u2019 book is the bestselling result. It has been translated into three languages since, and<br \/>\nboth authors now have careers that further deliver\/describe the benefits for clients. The book ties the foundational<br \/>\naspects of DevOps, Continuous Integration pipelines, and tight lean-inspired feedback loops together to get a broad<br \/>\nand deep definition of how we should develop software collectively in 2010 and onwards.<\/p>\n<p>Anecdotally the pipelines thinking captures a linear representation of Mike Cohn\u2019s famous \u201cTest Pyramid\u201d from his 2009 book,<br \/>\n\u201cSucceeding with Agile&#8221;<span><a target=\"_blank\" href=\"https:\/\/www.amazon.com\/gp\/product\/0321579364\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>. See Mike\u2019s blog entry a month<br \/>\nlater too<span><a target=\"_blank\" href=\"https:\/\/www.mountaingoatsoftware.com\/blog\/the-forgotten-layer-of-the-test-automation-pyramid\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>,<br \/>\nas well as Martin\u2019s recap in 2012<span><a target=\"_blank\" href=\"https:\/\/martinfowler.com\/bliki\/TestPyramid.html\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<\/p>\n<p>Dan North<span><a target=\"_blank\" href=\"https:\/\/dannorth.net\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> (Mr. BDD), Chris Read<span><a target=\"_blank\" href=\"https:\/\/www.linkedin.com\/in\/devopscread\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span><br \/>\n(an unsung DevOps pioneer) and Sam Newman<span><a target=\"_blank\" href=\"http:\/\/samnewman.io\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> were also key in the AOL advances.<br \/>\nDan North gave a deeper account of the mission at GOTO in 2014<span><a target=\"_blank\" href=\"https:\/\/speakerdeck.com\/tastapod\/the-birth-of-devops\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span><br \/>\n(no video sadly) and was interviewed later by InfoQ<span><a target=\"_blank\" href=\"https:\/\/www.infoq.com\/news\/2014\/07\/birth-cd-devops\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<\/p>\n<p>A year or so before that mission, Sam and Dave were on a different client, UK retailer \u2018Dixons\u2019. They were part of a team rolling out<br \/>\nemergent DevOps practices, which they would get to reuse and refine on the following AOL mission. Standouts were:<\/p>\n<ol>\n<li>making the test environments have consistent behavior with production environments (very close by not quite \u2018Infrastructure as Code\u2019)<\/li>\n<li>QA automation technologies setup by the dev team<\/li>\n<li>inducting\/co-locating individual QAs with the dev team<\/li>\n<li>Test Driven Development (TDD)<\/li>\n<li>Acceptance Test Driven development (ATDD)<\/li>\n<li>a CI pipeline that included performance tests<\/li>\n<li>a focus of team dynamics for high throughput<\/li>\n<\/ol>\n<h2 id=\"travis-cis-github-integration-and-passfail-badges-2011\">Travis-CI\u2019s GitHub integration and pass\/fail badges (2011)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd1.png\" alt><\/p>\n<p>In 2011, Travis-CI<span><a target=\"_blank\" href=\"https:\/\/travis-ci.com\/\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> provided easy integrations into GitHub\u2019s platform run CI<br \/>\nbuilds for Pull Requests and the general state of HEAD on any branch. This was visually indicated with \u201cbuild passes\u201d and<br \/>\n\u201cbuild fails\u201d badges were inserted into the GitHub UI<span><a target=\"_blank\" href=\"https:\/\/docs.travis-ci.com\/user\/status-images\/\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<br \/>\nThis made it was clear whether the proposed PR would break the build or not were it to be merged into trunk.<\/p>\n<h2 id=\"microservices-2011-and-2012\">Microservices (2011 and 2012)<\/h2>\n<p>The emergence of micro-services as small buildable\/deployable things that are glued together with TCP\/IP (and<br \/>\nXML\/YAML\/DNS configuration) reinforced \u201cmany small repositories\u201d (they kind of reinforce each other really), while this can be<br \/>\ndone with any branching model, the non-trunk models probably had the mindshare. Monorepos were out completely. A<br \/>\npossibility from monorepos teams sharing code and source level a HEAD revision, positively laughed it. The history<br \/>\npage of Wikipedia lists multiple people concurrently pushing the same emergent micro-service<br \/>\nidea<span><a target=\"_blank\" href=\"https:\/\/en.wikipedia.org\/wiki\/Microservices#History\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<\/p>\n<h2 id=\"case-study-a-practical-approach-to-large-scale-agile-development-2012\">Case Study: A Practical Approach To Large-Scale Agile Development (2012)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd1.png\" alt><\/p>\n<p>Gary Gruver, Mike Young, and Pat Fulghum wrote<br \/>\n\u201cA Practical Approach To Large-Scale Agile Development&#8221;<span><a target=\"_blank\" href=\"https:\/\/www.amazon.com\/dp\/0321821726\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span><br \/>\nto describe the multi-year<br \/>\ntransformation programme in the HP LaserJet Firmware division. In 2008, there were over 400 engineers dotted around<br \/>\nthe world working on over 10 million lines of printer firmware code in the HP LaserJet Firmware division. There<br \/>\nwere 10+ long-lived release feature branches (one for each product variant), with 1 week required for a build and<br \/>\n6 weeks required for manual regression testing. The engineers spent 25% of their time working on product support i.e.<br \/>\nmerging features between branches and only 5% of their time on new features.<\/p>\n<p>For the next couple of years, HP committed to a huge investment in Trunk-Based Development and<br \/>\nContinuous Integration. All product variants were re-architected as a single product on a Git super-repo, per-variant<br \/>\nfeatures extracted into XML config files, all engineers worldwide were given the same virtual machine for development,<br \/>\nand a huge multi-tier continuous build process was fully automated in-house. The results were outstanding, with build<br \/>\ntime reduced to 1 hour and manual testing replaced with a 24 hour fully automated test suite including printing<br \/>\ntest pages. 10-15 builds could be produced a day, engineers spent 5% of their time not 25% on product support and 40%<br \/>\nof their time not 5% of their time on new features. That is an 8x increase in productivity for 400 engineers.<\/p>\n<h2 id=\"traviscis-per-commit-speculative-mergeability-analysis-2012\">TravisCI\u2019s per-commit speculative mergeability analysis (2012)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd1.png\" alt><\/p>\n<p>TravisCI was the first<span><a target=\"_blank\" href=\"https:\/\/blog.travis-ci.com\/announcing-pull-request-support\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> CI service to<br \/>\nautomatically predict a GitHub pull-request\u2019s mergeability AND build success\/failure<br \/>\nas if they had landed in main\/trunk. Specifically:<\/p>\n<ol>\n<li>a speculative merge back to the main\/trunk\/mainline &#8211; only into working-copy as it is for analysis only<\/li>\n<li>all the classic compile\/unit-test\/integration-test\/functional-test steps of the regular build, in situ<\/li>\n<\/ol>\n<p>The speculative merge is discarded every time after #1 (if it can\u2019t merge) or #2 (regardless) &#8211;<br \/>\nthe actual merge result is never pushed off the build server to the remote (in Git terms). It is only the \u201cis this<br \/>\nbuildable and mergeable or not\u201d notification that was desired from the exercise.<\/p>\n<p>This feature of TravisCI is for <a href=\"https:\/\/trunkbaseddevelopment.com\/short-lived-feature-branches\/\">short-lived feature branches<\/a>,<br \/>\nit is clear now that teams should do<br \/>\nthis CI setup <strong>regardless of their branching model<\/strong>. Yes, even the long-lived branching models also benefit from this,<br \/>\nthough they\u2019ll be challenged to stay \u2018green\u2019 the whole time, and remain eminently and automatically mergeable back to<br \/>\nthe mainline\/main.<\/p>\n<p>A few months later, Team City implemented the same feature &#8211; <span><a target=\"_blank\" href=\"http:\/\/tech.labs.oliverwyman.com\/blog\/2013\/01\/13\/continuous-integration-for-github-pull-requests-with-teamcity\/\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>,<br \/>\nand a year later Snap-CI also did<span><a target=\"_blank\" href=\"https:\/\/blog.snap-ci.com\/blog\/2013\/11\/07\/automatic-branch-tracking-and-integration\/\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span><\/p>\n<p>What is a reality<br \/>\nin 2017 is that the high bar is every commit, <strong>every branch<\/strong>, with that speculative merge, and elastically scaled so<br \/>\nthat the notification is within seconds of pushing the commit to the shared VCS. Back in 2001 (CruiseControl) we were batching<br \/>\ncommits, we would wait a little while to allow checkins to finish (particularly for the non-atomic CVS), and humans would<br \/>\nhave to pick apart who actually broke the build.<\/p>\n<p>Surely teams not doing Trunk-Based Development would turn on this speculative merge and build capability for every branch and soon after plan their migration to Trunk-Based Development.<\/p>\n<h2 id=\"plasticscms-semantic-merge-2013\">PlasticSCM\u2019s semantic merge (2013)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/away_from_tbd1.png\" alt><\/p>\n<p>Plastic\u2019s semantic diff and merge<span><a target=\"_blank\" href=\"http:\/\/semanticmerge.com\/\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> capability was launched in March<br \/>\n2013<span><a target=\"_blank\" href=\"https:\/\/www.infoq.com\/news\/2013\/04\/Semantic-Merge\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>. It allowed a greatly reduced diff for<br \/>\nrefactoring commits.<\/p>\n<p>If merges between branches are required, and larger<br \/>\ncode changes (like refactorings) are desired, then multi-branch development is a little easier with this. However, Trunk Based<br \/>\nDevelopment\u2019s commits are more elegant too, because of it, and in the fullness of time, it might make<br \/>\non techniques like Branch by Abstraction easier, or reduce the need for it, if merge conflicts happen less often<br \/>\n(according to source-control) for something in 2012 that would have been a definite clash.<\/p>\n<p>Other source-control tools are not doing semantic diff\/merge yet (2017), but they should be. Semantic merge is<br \/>\njust as useful for Trunk-Based Development and multi-branch models. It means that there are less likely to be clash<br \/>\nsituations for commits a developer wants to do. Maybe that last vision is not quite complete yet, but there\u2019s a direction<br \/>\nto go in now.<\/p>\n<h2 id=\"google-revealing-their-monorepo-trunk-2016\">Google revealing their Monorepo Trunk (2016)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd3.png\" alt><\/p>\n<p>In none other than the Association for Computing Machinery\u2019s magazine, Googlers Rachel Potvin and Josh Levenberg share<br \/>\nhow Google arranges for 95% (25,000) of its software developers to share one trunk in \u201cWhy Google Stores Billions of<br \/>\nLines of Code in a Single Repository&#8221;<span><a target=\"_blank\" href=\"http:\/\/cacm.acm.org\/magazines\/2016\/7\/204032-why-google-stores-billions-of-lines-of-code-in-a-single-repository\/fulltext\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<br \/>\nThey use a <a href=\"https:\/\/trunkbaseddevelopment.com\/monorepos\/\">Monorepo<\/a> variant of a trunk, with internal code shared at <strong>source level<\/strong>, for high-throughput,<br \/>\nlow-defect delivery of multiple applications and services. Each application\/service has a release cadence chosen by the dev+biz<br \/>\nteam in question. Yes, everything works just fine.<\/p>\n<p>A couple of months later, Rachel Potvin presented at the @Scale Conference on the same topic<span><a target=\"_blank\" href=\"https:\/\/youtu.be\/W71BTkUbdqE\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> &#8211; \u201cWhy Google Stores Billions of Lines of Code in a<br \/>\nSingle Repository\u201d:<\/p>\n<h2 id=\"microsofts-git-virtual-file-system-2017\">Microsoft\u2019s Git Virtual File System (2017)<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/trunkbaseddevelopment.com\/to_tbd1.png\" alt><\/p>\n<p>Microsoft released <del>GitVFS<\/del> GVFS in early 2017 on GitHub<span><a target=\"_blank\" href=\"https:\/\/github.com\/Microsoft\/GVFS\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span>.<\/p>\n<p>This new technology deserves time and analysis before the full impact is determined. There is a suggestion from Brian Harry\u2019s<br \/>\nblog<span><a target=\"_blank\" href=\"https:\/\/blogs.msdn.microsoft.com\/bharry\/2017\/02\/07\/more-on-gvfs\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/trunkbaseddevelopment.com\/images\/ext.png\" alt><\/a><\/span> that branch reduction was one of<br \/>\nthe motivators.<\/p>\n<h2 id=\"references-elsewhere\">References elsewhere<\/h2>\n<p>show references<\/p>\n<\/p><\/div>\n<p><a href=\"https:\/\/trunkbaseddevelopment.com\/game-changers\/\" class=\"button purchase\" rel=\"nofollow noopener\" target=\"_blank\">Read More<\/a><br \/>\n Alejandro Mcnaught<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Game Changers Since the early 80\u2019s a number of things have pushed best practices towards Trunk-Based Development, or away from it. The language in use to describe such things has changed over time. Software Configuration Management (SCM) is used less today than Version Control Systems (VCS) is. A simpler still term &#8211; \u201cSource Control\u201d &#8211;<\/p>\n","protected":false},"author":1,"featured_media":606595,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27400,46,119022],"tags":[],"class_list":{"0":"post-606594","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-development","8":"category-technology","9":"category-trunk-based"},"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/posts\/606594","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/comments?post=606594"}],"version-history":[{"count":0,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/posts\/606594\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/media\/606595"}],"wp:attachment":[{"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/media?parent=606594"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/categories?post=606594"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/tags?post=606594"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}