[{"data":1,"prerenderedAt":1536},["ShallowReactive",2],{"post-cards":3,"categories":529,"post-improve-your-git-workflow-with-git-flow":567},[4,27,38,54,68,78,87,97,111,124,134,145,160,172,185,196,207,218,229,240,251,264,277,292,307,321,335,347,358,369,379,389,399,409,419,429,439,449,459,469,479,489,499,509,519],{"path":5,"title":6,"slug":7,"summary":8,"date":9,"readTime":10,"hasImage":11,"category":12,"tags":17,"tagSlugs":26},"\u002Fposts\u002Fgit-flow-vs-github-flow-choosing-a-branching-strategy","Git Flow vs GitHub Flow: Choosing a Branching Strategy for Your Team","git-flow-vs-github-flow-choosing-a-branching-strategy","Git Flow and GitHub Flow take very different approaches to team branching and releases. Let's compare them, see where trunk-based development fits, and sort out how to handle versioned releases, hotfixes, and everything in between.","2026-06-14",7,false,{"id":13,"name":14,"slug":15,"hue":16},4,"Git","git",158,[18,20,23],{"name":19,"slug":15},"GIT",{"name":21,"slug":22},"Workflow","workflow",{"name":24,"slug":25},"GitHub","github",[15,22,25],{"path":28,"title":29,"slug":30,"summary":31,"date":9,"readTime":10,"hasImage":11,"category":32,"tags":33,"tagSlugs":37},"\u002Fposts\u002Fgithub-flow-keep-your-main-branch-deployable","GitHub Flow: Keep Your Main Branch Deployable","github-flow-keep-your-main-branch-deployable","GitHub Flow is the lightweight branching workflow built on a single rule: anything in main is deployable. Here is the whole loop, branch, pull request, review, merge and deploy, with the git and gh commands and an honest look at where it fits.",{"id":13,"name":14,"slug":15,"hue":16},[34,35,36],{"name":19,"slug":15},{"name":21,"slug":22},{"name":24,"slug":25},[15,22,25],{"path":39,"title":40,"slug":41,"summary":42,"date":43,"readTime":44,"hasImage":11,"category":45,"tags":50,"tagSlugs":53},"\u002Fposts\u002Fstarting-with-rust-installation-first-program","Starting with Rust: From Installation to Your First Program","starting-with-rust-installation-first-program","Learn how to install Rust and write your first \"Hello, world!\" program.","2024-03-23",2,{"id":46,"name":47,"slug":48,"hue":49},6,"Rust","rust-programming",38,[51],{"name":52,"slug":52},"rust",[52],{"path":55,"title":56,"slug":57,"summary":58,"date":59,"readTime":44,"hasImage":11,"category":60,"tags":65,"tagSlugs":67},"\u002Fposts\u002Fflutter-version-management-fvm","Flutter Version Management","flutter-version-management-fvm","Managing multiple Flutter versions does not need not be a headache. Let's jump into FVM and see how it can simplify your Flutter journey.","2023-10-07",{"id":61,"name":62,"slug":63,"hue":64},5,"Flutter","flutter",230,[66],{"name":63,"slug":63},[63],{"path":69,"title":70,"slug":71,"summary":72,"date":59,"readTime":73,"hasImage":11,"category":74,"tags":75,"tagSlugs":77},"\u002Fposts\u002Fsetting-up-cocoapods-fvm","Setting Up CocoaPods for FVM-managed Flutter Projects","setting-up-cocoapods-fvm","A guide to installing CocoaPods for a Flutter project while using FVM to manage Flutter versions, ensuring a smooth setup for iOS development.",1,{"id":61,"name":62,"slug":63,"hue":64},[76],{"name":63,"slug":63},[63],{"path":79,"title":80,"slug":81,"summary":82,"date":59,"readTime":73,"hasImage":11,"category":83,"tags":84,"tagSlugs":86},"\u002Fposts\u002Ftroubleshooting-xcode-15-build-issues-flutter","Troubleshooting Xcode 15 Build Issues in Flutter Projects","troubleshooting-xcode-15-build-issues-flutter","Uncovering solutions to common issues faced when updating to Xcode 15 in a Flutter project using an older version of CocoaPods.",{"id":61,"name":62,"slug":63,"hue":64},[85],{"name":63,"slug":63},[63],{"path":88,"title":89,"slug":90,"summary":91,"date":92,"readTime":13,"hasImage":11,"category":93,"tags":94,"tagSlugs":96},"\u002Fposts\u002Fgit-tracking-a-remote-branch-upstream-for-changes","Git: Tracking a Remote Branch for Changes","git-tracking-a-remote-branch-upstream-for-changes","When you fork a project, you need a way to pull in changes from the original repository, usually called upstream. Here is how to wire up an upstream remote, actually sync your fork, and set up branch tracking so plain git pull and git push just work.","2018-11-04",{"id":13,"name":14,"slug":15,"hue":16},[95],{"name":19,"slug":15},[15],{"path":98,"title":99,"slug":100,"summary":101,"date":92,"readTime":102,"hasImage":103,"category":104,"tags":108,"tagSlugs":110},"\u002Fposts\u002Fjavascript-array-map-filter-reduce-functions","JavaScript's map, filter, and reduce methods","javascript-array-map-filter-reduce-functions","JavaScript provides some amazing functions that can be called against your arrays to help filter them, manipulate them, or even reduce them down to a single value or grouped values.",3,true,{"id":44,"name":105,"slug":106,"hue":107},"JavaScript","javascript",92,[109],{"name":105,"slug":106},[106],{"path":112,"title":113,"slug":114,"summary":115,"date":116,"readTime":73,"hasImage":103,"category":117,"tags":121,"tagSlugs":123},"\u002Fposts\u002Fphp-fizzbuzz-example","FizzBuzz in PHP: A Fresh Approach","php-fizzbuzz-example","FizzBuzz is a very popular programming question that tests your logic to see if you can build a simple program.","2018-11-02",{"id":73,"name":118,"slug":119,"hue":120},"PHP","php",264,[122],{"name":118,"slug":119},[119],{"path":125,"title":126,"slug":127,"summary":128,"date":129,"readTime":44,"hasImage":103,"category":130,"tags":131,"tagSlugs":133},"\u002Fposts\u002Fphp-array-reduce","PHP's array_reduce is not only for outputting single values","php-array-reduce","PHP's array_reduce is a simple way to partition a set of data or return a single value. It is super powerful and worth spending time learning.","2018-11-01",{"id":73,"name":118,"slug":119,"hue":120},[132],{"name":118,"slug":119},[119],{"path":135,"title":136,"slug":137,"summary":138,"date":139,"readTime":46,"hasImage":11,"category":140,"tags":141,"tagSlugs":144},"\u002Fposts\u002Fimprove-your-git-workflow-with-git-flow","Improve Your Git Workflow with Git Flow","improve-your-git-workflow-with-git-flow","Git Flow is a structured branching model built around versioned, scheduled releases. Here is how its branches fit together, a hands-on walkthrough of features, releases and hotfixes, and an honest take on when it is still the right call.","2016-12-06",{"id":13,"name":14,"slug":15,"hue":16},[142,143],{"name":19,"slug":15},{"name":21,"slug":22},[15,22],{"path":146,"title":147,"slug":148,"summary":149,"date":150,"readTime":46,"hasImage":11,"category":151,"tags":155,"tagSlugs":159},"\u002Fposts\u002Fusing-css-transitions","Using CSS Transitions","using-css-transitions","CSS transitions are the standard way to apply transitions to your elements, and have been for years, replacing the old approach of using JavaScript. In this article, I'll go through each of the transition properties available, and provide examples of how to use them.","2016-12-05",{"id":102,"name":152,"slug":153,"hue":154},"HTML & CSS","html-css",55,[156],{"name":157,"slug":158},"CSS","css",[158],{"path":161,"title":162,"slug":163,"summary":164,"date":165,"readTime":13,"hasImage":11,"category":166,"tags":167,"tagSlugs":171},"\u002Fposts\u002Fstructuring-your-website-with-html-5-semantics","Structuring Your Website With HTML 5 Semantics","structuring-your-website-with-html-5-semantics","Prior to HTML 5, there was no real markup to help explain the intent behind your HTML code. The goal of HTML 5 was to offer a more readable way of writing your code, so that any author that comes after you can have an easier time going through what you've created.","2016-12-04",{"id":102,"name":152,"slug":153,"hue":154},[168],{"name":169,"slug":170},"HTML","html",[170],{"path":173,"title":174,"slug":175,"summary":176,"date":177,"readTime":44,"hasImage":11,"category":178,"tags":179,"tagSlugs":184},"\u002Fposts\u002Finterpolation-in-stylus-css-pre-processor","Interpolation in Stylus","interpolation-in-stylus-css-pre-processor","You can also use interpolation to improve your functions for reuse, as well as your other code within your stylesheet. The way it works is that you can wrap your expression within {}, which will then be outputted as the identifier.","2016-12-03",{"id":102,"name":152,"slug":153,"hue":154},[180,183],{"name":181,"slug":182},"Stylus","stylus",{"name":157,"slug":158},[182,158],{"path":186,"title":187,"slug":188,"summary":189,"date":190,"readTime":73,"hasImage":11,"category":191,"tags":192,"tagSlugs":195},"\u002Fposts\u002Fcreating-configuration-files-in-stylus-css-pre-processor","Creating Configuration Files In Stylus","creating-configuration-files-in-stylus-css-pre-processor","It's super simple to create a configuration file for instance that would manage your media query break points. You could also use a configuration file for managing colors, font sizes, and other variables such as gutter spacing and more.","2016-12-02",{"id":102,"name":152,"slug":153,"hue":154},[193,194],{"name":157,"slug":158},{"name":181,"slug":182},[158,182],{"path":197,"title":198,"slug":199,"summary":200,"date":201,"readTime":13,"hasImage":11,"category":202,"tags":203,"tagSlugs":206},"\u002Fposts\u002Fusing-functions-and-mixins-with-stylus-css-pre-processor","Using Functions and Mixins with Stylus","using-functions-and-mixins-with-stylus-css-pre-processor","Stylus allows you to create functions and mixins of reusable code for your stylesheets. You can also handle mathematical operations, unary operations, and more allowing you complete control over your stylesheets with ease.","2016-12-01",{"id":102,"name":152,"slug":153,"hue":154},[204,205],{"name":157,"slug":158},{"name":181,"slug":182},[158,182],{"path":208,"title":209,"slug":210,"summary":211,"date":212,"readTime":44,"hasImage":11,"category":213,"tags":214,"tagSlugs":217},"\u002Fposts\u002Fsetting-variables-in-stylus-css-pre-processor","Setting Variables in Stylus","setting-variables-in-stylus-css-pre-processor","Unlike CSS, in Stylus you can assign expressions to variables that can be reusable throughout your stylesheets.","2016-11-29",{"id":102,"name":152,"slug":153,"hue":154},[215,216],{"name":157,"slug":158},{"name":181,"slug":182},[158,182],{"path":219,"title":220,"slug":221,"summary":222,"date":223,"readTime":61,"hasImage":11,"category":224,"tags":225,"tagSlugs":228},"\u002Fposts\u002Fusing-selectors-in-stylus-css-pre-processor","Using Selectors in Stylus","using-selectors-in-stylus-css-pre-processor","Selectors are a way to pick the elements that you want styled. In Stylus, similar to CSS, you can apply a set of styles to any element by separating them by a comma delimited list. Stylus though, also allows you to select multiple elements by separating each on their own line.","2016-11-28",{"id":102,"name":152,"slug":153,"hue":154},[226,227],{"name":157,"slug":158},{"name":181,"slug":182},[158,182],{"path":230,"title":231,"slug":232,"summary":233,"date":234,"readTime":73,"hasImage":11,"category":235,"tags":236,"tagSlugs":239},"\u002Fposts\u002Flearning-stylus-a-css-pre-processor","Learning Stylus: A CSS Pre-Processor","learning-stylus-a-css-pre-processor","This mini-series will be a little different to how you may see other articles on my site. Really this article is more geared as notes for me as I go through the documentation for Stylus, and learn the ins and outs of this beautiful language.","2016-11-27",{"id":102,"name":152,"slug":153,"hue":154},[237,238],{"name":157,"slug":158},{"name":181,"slug":182},[158,182],{"path":241,"title":242,"slug":243,"summary":244,"date":245,"readTime":13,"hasImage":11,"category":246,"tags":247,"tagSlugs":250},"\u002Fposts\u002Fbem-methodology-overview-and-naming-conventions","BEM Methodology Overview and Naming Conventions","bem-methodology-overview-and-naming-conventions","BEM or Block Element Modifier is a naming convention used to help organize your code base. In this article, I discuss its uses within your CSS projects.","2016-11-26",{"id":102,"name":152,"slug":153,"hue":154},[248,249],{"name":157,"slug":158},{"name":169,"slug":170},[158,170],{"path":252,"title":253,"slug":254,"summary":255,"date":256,"readTime":73,"hasImage":11,"category":257,"tags":258,"tagSlugs":263},"\u002Fposts\u002Fintroduction-to-ecmascript-6","Introduction to ECMAScript 6","introduction-to-ecmascript-6","The latest in ECMAScript 6 introduces new features to JavaScript which makes it so much more fun to use, while solving problems that have been around for years. The intent of this article is to provide you with resources you can use to start learning ES6 today.","2016-11-25",{"id":44,"name":105,"slug":106,"hue":107},[259,260],{"name":105,"slug":106},{"name":261,"slug":262},"ECMAScript","ecmascript",[106,262],{"path":265,"title":266,"slug":267,"summary":268,"date":269,"readTime":102,"hasImage":11,"category":270,"tags":271,"tagSlugs":276},"\u002Fposts\u002Fbabel-installation-and-configuration","Babel Installation and Configuration","babel-installation-and-configuration","Babel offers a convenient way to transform your ES6 code to JavaScript that all browsers can understand. In this article we'll go over a basic configuration that will enable you to start using it with any project right away.","2016-11-24",{"id":44,"name":105,"slug":106,"hue":107},[272,273],{"name":105,"slug":106},{"name":274,"slug":275},"Babel","babel",[106,275],{"path":278,"title":279,"slug":280,"summary":281,"date":282,"readTime":73,"hasImage":11,"category":283,"tags":284,"tagSlugs":291},"\u002Fposts\u002Fconfiguring-stylus-css-pre-processor-with-gulp-and-sourcemaps","Configuring Stylus CSS Pre-Processor with Gulp and Sourcemaps","configuring-stylus-css-pre-processor-with-gulp-and-sourcemaps","In this article we'll go over how to configure your project to process Stylus files using Gulp. We'll also create source map file which your browser will use to help point you in the right direction of your files when developing","2016-11-23",{"id":44,"name":105,"slug":106,"hue":107},[285,286,287,288],{"name":105,"slug":106},{"name":181,"slug":182},{"name":157,"slug":158},{"name":289,"slug":290},"Gulp","gulp",[106,182,158,290],{"path":293,"title":294,"slug":295,"summary":296,"date":297,"readTime":44,"hasImage":11,"category":298,"tags":299,"tagSlugs":306},"\u002Fposts\u002Fconfiguring-gulp-with-less-css-pre-processor","Configuring Gulp With Less CSS Pre-Processor","configuring-gulp-with-less-css-pre-processor","Less is a CSS pre-processor allowing you to create variables, mixins, and functions in an effort to make your CSS more maintainable.","2016-11-22",{"id":44,"name":105,"slug":106,"hue":107},[300,301,302,305],{"name":289,"slug":290},{"name":105,"slug":106},{"name":303,"slug":304},"Less","less",{"name":157,"slug":158},[290,106,304,158],{"path":308,"title":309,"slug":310,"summary":311,"date":312,"readTime":44,"hasImage":103,"category":313,"tags":314,"tagSlugs":320},"\u002Fposts\u002Fusing-browser-sync-with-gulp-for-live-reloading","Using Browser Sync with Gulp for Live Reloading","using-browser-sync-with-gulp-for-live-reloading","Browser Sync is a nice tool to use while developing. It allows your browser to reload live when changes are made to your files. For instance, assuming we're watching our CSS file for changes we can have the browser auto refresh\u002Fsync when it sees those changes made.","2016-11-21",{"id":44,"name":105,"slug":106,"hue":107},[315,316,319],{"name":105,"slug":106},{"name":317,"slug":318},"Browser Sync","browser-sync",{"name":289,"slug":290},[106,318,290],{"path":322,"title":323,"slug":324,"summary":325,"date":326,"readTime":44,"hasImage":11,"category":327,"tags":328,"tagSlugs":334},"\u002Fposts\u002Fgulp-watch-automate-your-gulp-tasks","Gulp Watch: Automate Your Gulp Tasks","gulp-watch-automate-your-gulp-tasks","Gulp watch is perfect for when you're editing project files since it allows you to not have to run the gulp command manually each time.","2016-11-20",{"id":44,"name":105,"slug":106,"hue":107},[329,330,333],{"name":105,"slug":106},{"name":331,"slug":332},"Yarn","yarn",{"name":289,"slug":290},[106,332,290],{"path":336,"title":337,"slug":338,"summary":339,"date":340,"readTime":46,"hasImage":11,"category":341,"tags":342,"tagSlugs":346},"\u002Fposts\u002Fconfiguring-gulp-on-a-new-project","Configuring Gulp On A New Project","configuring-gulp-on-a-new-project","Gulp may seem like a scary thing to wrap your head around at first, but it's actually quite easy to start using once you understand the basics.","2016-11-19",{"id":44,"name":105,"slug":106,"hue":107},[343,344,345],{"name":105,"slug":106},{"name":289,"slug":290},{"name":331,"slug":332},[106,290,332],{"path":348,"title":349,"slug":350,"summary":351,"date":352,"readTime":102,"hasImage":11,"category":353,"tags":354,"tagSlugs":357},"\u002Fposts\u002Fyarn-publishing-a-package","Yarn: Publishing a Package","yarn-publishing-a-package","Publishing a package to the npm repository has never been simpler. With a few steps, you can create a package that is redistributable to all of your projects.","2016-11-18",{"id":44,"name":105,"slug":106,"hue":107},[355,356],{"name":105,"slug":106},{"name":331,"slug":332},[106,332],{"path":359,"title":360,"slug":361,"summary":362,"date":363,"readTime":102,"hasImage":11,"category":364,"tags":365,"tagSlugs":368},"\u002Fposts\u002Fyarn-fast-and-secure-dependency-management","Yarn: Fast and Secure Dependency Management","yarn-fast-and-secure-dependency-management","Yarn is a super simple dependency management tool which is way faster to use instead of traditional npm. It acts as a drop-in replacement, so you can get started using yarn right away. The best way to install yarn is by using npm.","2016-11-17",{"id":44,"name":105,"slug":106,"hue":107},[366,367],{"name":105,"slug":106},{"name":331,"slug":332},[106,332],{"path":370,"title":371,"slug":372,"summary":373,"date":374,"readTime":73,"hasImage":103,"category":375,"tags":376,"tagSlugs":378},"\u002Fposts\u002Fsupport-for-keys-in-list-or-its-new-shorthand-syntax-in-php","Support for keys in list(), or its new shorthand syntax [] in PHP","support-for-keys-in-list-or-its-new-shorthand-syntax-in-php","Now as of PHP 7.1, you can define the keys of your array that will be parsed when destructuring your arrays. Prior to PHP 7.1, you could only use arrays with numeric indexes. Now with this new addition, our lives just got easier.","2016-11-16",{"id":73,"name":118,"slug":119,"hue":120},[377],{"name":118,"slug":119},[119],{"path":380,"title":381,"slug":382,"summary":383,"date":384,"readTime":73,"hasImage":103,"category":385,"tags":386,"tagSlugs":388},"\u002Fposts\u002Ftype-hinting-with-the-iterable-pseudo-type-in-php","Type Hinting With The Iterable pseudo-type In PHP","type-hinting-with-the-iterable-pseudo-type-in-php","As of PHP 7.1, you can now type hint your method\u002Ffunction arguments with the keyword iterable for handling arrays or even objects that implement the Traversable interface.","2016-11-15",{"id":73,"name":118,"slug":119,"hue":120},[387],{"name":118,"slug":119},[119],{"path":390,"title":391,"slug":392,"summary":393,"date":394,"readTime":73,"hasImage":103,"category":395,"tags":396,"tagSlugs":398},"\u002Fposts\u002Ftype-hinting-callable-functions-in-php","Type Hinting Callable Functions in PHP","type-hinting-callable-functions-in-php","As of PHP 5.4, you can type hint your method arguments with the callable keyword allowing you to enforce the type of data that is passed via your arguments.","2016-11-14",{"id":73,"name":118,"slug":119,"hue":120},[397],{"name":118,"slug":119},[119],{"path":400,"title":401,"slug":402,"summary":403,"date":404,"readTime":73,"hasImage":103,"category":405,"tags":406,"tagSlugs":408},"\u002Fposts\u002Fsetting-visibility-for-your-class-constants-in-php","Setting Visibility for Your Class Constants in PHP","setting-visibility-for-your-class-constants-in-php","Now in PHP 7.1+, you can set different visibility modifiers for each of your class constants. The available visibility modifiers consist of public, protected, and private.","2016-11-13",{"id":73,"name":118,"slug":119,"hue":120},[407],{"name":118,"slug":119},[119],{"path":410,"title":411,"slug":412,"summary":413,"date":414,"readTime":73,"hasImage":103,"category":415,"tags":416,"tagSlugs":418},"\u002Fposts\u002Fanonymous-classes-php","Using Anonymous Classes in PHP","anonymous-classes-php","As of PHP 7, you can now create quick throwaway objects for use within your projects. This can be especially useful for your automated tests, for instance, with allowing you to create quick implementations of your interfaces.","2016-11-12",{"id":73,"name":118,"slug":119,"hue":120},[417],{"name":118,"slug":119},[119],{"path":420,"title":421,"slug":422,"summary":423,"date":424,"readTime":73,"hasImage":103,"category":425,"tags":426,"tagSlugs":428},"\u002Fposts\u002Fsymmetric-array-destructuring-in-php","Symmetric Array Destructuring in PHP","symmetric-array-destructuring-in-php","As of PHP 7.1, you can now use the shorthand array syntax to destructure your arrays for assignment. Previously you would have had to use a function like list, but now you can use the simple new array shorthand syntax.","2016-11-11",{"id":73,"name":118,"slug":119,"hue":120},[427],{"name":118,"slug":119},[119],{"path":430,"title":431,"slug":432,"summary":433,"date":434,"readTime":44,"hasImage":103,"category":435,"tags":436,"tagSlugs":438},"\u002Fposts\u002Fphp-array-map-to-format-your-arrays-without-loops","Using PHP's array_map to format your arrays without loops","php-array-map-to-format-your-arrays-without-loops","So let's face it, loops are a bit boring. So how can we mix it up? Let's assume we have a case where we have a CSV file that we want to quickly parse.","2016-11-10",{"id":73,"name":118,"slug":119,"hue":120},[437],{"name":118,"slug":119},[119],{"path":440,"title":441,"slug":442,"summary":443,"date":444,"readTime":10,"hasImage":103,"category":445,"tags":446,"tagSlugs":448},"\u002Fposts\u002Fsolid-principles-in-php","SOLID Principles in PHP","solid-principles-in-php","The 5 basic principles for Object-Oriented Design, SOLID, were first created in an effort to improve maintainability in our code bases. SOLID is a mnemonic acronym that stands for each of the following principles: Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion.","2016-11-09",{"id":73,"name":118,"slug":119,"hue":120},[447],{"name":118,"slug":119},[119],{"path":450,"title":451,"slug":452,"summary":453,"date":454,"readTime":73,"hasImage":103,"category":455,"tags":456,"tagSlugs":458},"\u002Fposts\u002Ffiltering-arrays-without-using-loops-in-php","Filtering Arrays Without Using Loops in PHP","filtering-arrays-without-using-loops-in-php","PHP has a built-in function called array_filter that allows you to filter through your arrays without the need for a loop. Personally, this approach feels much cleaner to me and simpler to comprehend.","2016-11-08",{"id":73,"name":118,"slug":119,"hue":120},[457],{"name":118,"slug":119},[119],{"path":460,"title":461,"slug":462,"summary":463,"date":464,"readTime":73,"hasImage":103,"category":465,"tags":466,"tagSlugs":468},"\u002Fposts\u002Fvoid-return-types-in-php","Void Return Types in PHP","void-return-types-in-php","As of PHP 7.1, we can now use void return types within our methods. This is useful for cases where you have methods that are just setting or processing data without the need of returning any values.","2016-11-07",{"id":73,"name":118,"slug":119,"hue":120},[467],{"name":118,"slug":119},[119],{"path":470,"title":471,"slug":472,"summary":473,"date":474,"readTime":73,"hasImage":103,"category":475,"tags":476,"tagSlugs":478},"\u002Fposts\u002Ftype-hinting-with-nullable-types-in-php","Type Hinting with Nullable Types in PHP","type-hinting-with-nullable-types-in-php","As of PHP 7.1, you can now set your type declarations as nullable by simply prefixing them with a question mark ?. In doing so a null value can be passed in as a parameter or returned as a value for your methods.","2016-11-06",{"id":73,"name":118,"slug":119,"hue":120},[477],{"name":118,"slug":119},[119],{"path":480,"title":481,"slug":482,"summary":483,"date":484,"readTime":73,"hasImage":103,"category":485,"tags":486,"tagSlugs":488},"\u002Fposts\u002Fphp-group-multiple-use-declarations","PHP Group Multiple use Declarations","php-group-multiple-use-declarations","As of PHP 7, you can now group your imported classes, functions, and constants from under the same namespace.","2016-11-05",{"id":73,"name":118,"slug":119,"hue":120},[487],{"name":118,"slug":119},[119],{"path":490,"title":491,"slug":492,"summary":493,"date":494,"readTime":73,"hasImage":103,"category":495,"tags":496,"tagSlugs":498},"\u002Fposts\u002Fphp-null-coalescing-operator","PHP Null Coalescing Operator","php-null-coalescing-operator","One of my new favorite additions to PHP 7, is the Null Coalescing Operator. It cleans up your code by removing a tedious step of checking if some value is isset() and not NULL and returning it or if not setting a default.","2016-11-04",{"id":73,"name":118,"slug":119,"hue":120},[497],{"name":118,"slug":119},[119],{"path":500,"title":501,"slug":502,"summary":503,"date":504,"readTime":44,"hasImage":103,"category":505,"tags":506,"tagSlugs":508},"\u002Fposts\u002Fphp-spaceship-operator","PHP Spaceship Operator","php-spaceship-operator","One of the new features to hit PHP 7 is the Spaceship Operator. This new trick helps improve the way you'd compare 2 expressions. In short, the comparison returns 1 of 3 values (-1, 0, or 1) depending on the result of the comparison.","2016-11-03",{"id":73,"name":118,"slug":119,"hue":120},[507],{"name":118,"slug":119},[119],{"path":510,"title":511,"slug":512,"summary":513,"date":514,"readTime":102,"hasImage":103,"category":515,"tags":516,"tagSlugs":518},"\u002Fposts\u002Freturn-type-declarations-in-php","Return Type Declarations in PHP","return-type-declarations-in-php","PHP 7 now makes it possible to declare return types for your methods. This allows you better control over the data that will be returned from each method in your application.","2016-11-02",{"id":73,"name":118,"slug":119,"hue":120},[517],{"name":118,"slug":119},[119],{"path":520,"title":521,"slug":522,"summary":523,"date":524,"readTime":73,"hasImage":103,"category":525,"tags":526,"tagSlugs":528},"\u002Fposts\u002Fscalar-type-hints-php","Scalar Type Hints in PHP","scalar-type-hints-php","Starting with PHP 7.0, it's now possible to declare scalar type hints for your method arguments. Previously, we were able to use array and callable, but now with PHP 7+, we have much more control.","2016-11-01",{"id":73,"name":118,"slug":119,"hue":120},[527],{"name":118,"slug":119},[119],[530,537,543,549,555,561],{"id":531,"description":532,"extension":533,"hue":120,"meta":534,"name":118,"slug":119,"stem":535,"weight":73,"__hash__":536},"categories\u002Fcategories\u002Fphp.json","PHP articles and tutorials ranging from new language features to using interesting packages.","json",{},"categories\u002Fphp","h_EmN4YMO4b2mBt3MPLs7RvscJx0NBmwDIZPxqPqKLE",{"id":538,"description":539,"extension":533,"hue":107,"meta":540,"name":105,"slug":106,"stem":541,"weight":44,"__hash__":542},"categories\u002Fcategories\u002Fjavascript.json","JavaScript articles and tutorials ranging from new language features to using interesting packages.",{},"categories\u002Fjavascript","7gmVgkw5BRo26i1bFoSv96bwDJ4nTtZcJ9Ud6u5p0yk",{"id":544,"description":545,"extension":533,"hue":154,"meta":546,"name":152,"slug":153,"stem":547,"weight":102,"__hash__":548},"categories\u002Fcategories\u002Fhtml-css.json","HTML & CSS articles and tutorials ranging from new language features to using interesting packages.",{},"categories\u002Fhtml-css","vXvPlRA-iaeCJ64Wi3sLyUR0kqL48zYcZWORRqt8N70",{"id":550,"description":551,"extension":533,"hue":16,"meta":552,"name":14,"slug":15,"stem":553,"weight":13,"__hash__":554},"categories\u002Fcategories\u002Fgit.json","Git articles and tutorials ranging from new language features to different workflows.",{},"categories\u002Fgit","qOqFsFTKI9XB444UodUKW_3AakFadHzW-ss8V-maUmE",{"id":556,"description":557,"extension":533,"hue":64,"meta":558,"name":62,"slug":63,"stem":559,"weight":61,"__hash__":560},"categories\u002Fcategories\u002Fflutter.json","Dive into Flutter, the open-source UI software development toolkit, as we explore its capabilities in creating natively compiled applications for mobile, web, and desktop from a single codebase.",{},"categories\u002Fflutter","aD1moU8CgoYt4FRnSeA4Iy9xxnnopdEKBEYP2arAzdI",{"id":562,"description":563,"extension":533,"hue":49,"meta":564,"name":47,"slug":48,"stem":565,"weight":46,"__hash__":566},"categories\u002Fcategories\u002Frust-programming.json","From setting up your environment to advanced concepts, this is your go-to resource for all things Rust.",{},"categories\u002Frust-programming","LscnqSsk-htWc9yZg9eXaIUJwNfTK5oaZOClYKagNC4",{"id":568,"title":136,"body":569,"category":1526,"date":139,"description":575,"extension":1527,"hasImage":11,"meta":1528,"navigation":103,"path":135,"readTime":46,"seo":1529,"slug":137,"stem":1530,"summary":138,"tagSlugs":1531,"tags":1532,"__hash__":1535},"posts\u002Fposts\u002Fimprove-your-git-workflow-with-git-flow.md",{"type":570,"value":571,"toc":1515},"minimark",[572,576,581,584,587,601,604,608,611,640,643,677,686,690,696,784,790,796,823,827,837,857,860,907,917,923,957,961,974,1023,1029,1083,1095,1133,1137,1146,1164,1167,1184,1207,1302,1306,1320,1347,1353,1357,1364,1481,1495,1499,1505,1511],[573,574,575],"p",{},"Git Flow is a development workflow for keeping branching consistent across a team. It was the workflow everyone copied for years, and it is still a great fit for certain kinds of projects. In this article I will walk through the branches it uses, show a hands-on example of features, releases and hotfixes, and give you an honest read on when to reach for it.",[577,578,580],"h2",{"id":579},"is-git-flow-still-the-right-choice","Is Git Flow still the right choice?",[573,582,583],{},"Let's get the reality check out of the way first, because it changes how you should read the rest of this post.",[573,585,586],{},"Git Flow comes from Vincent Driessen's 2010 article \"A successful Git branching model.\" In 2020 he added a note to the top of that same article saying that if your team practices continuous delivery, you should probably adopt something simpler like GitHub Flow, and that Git Flow still fits teams building explicitly versioned software or supporting multiple versions in the wild. Atlassian now describes Git Flow as a legacy workflow, one that has lost ground to trunk-based development for modern CI\u002FCD.",[573,588,589,590,595,596,600],{},"None of that makes it wrong. It just means the extra branches are overhead you only want to pay for when versioned releases actually earn it. Think desktop apps, libraries, mobile releases, SDKs, anything where multiple versions live in the world at once and need separate maintenance. If you are shipping a web app that deploys continuously, skip ahead to ",[591,592,594],"a",{"href":593},"\u002Farticles\u002Fgithub-flow-keep-your-main-branch-deployable","GitHub Flow",", or read my ",[591,597,599],{"href":598},"\u002Farticles\u002Fgit-flow-vs-github-flow-choosing-a-branching-strategy","Git Flow vs GitHub Flow comparison"," for the full head to head.",[573,602,603],{},"Still here? Then you probably ship versions, and Git Flow's structure is going to serve you well. Let's get into it.",[577,605,607],{"id":606},"the-branches","The branches",[573,609,610],{},"Git Flow uses two long-lived branches plus three kinds of supporting branches.",[612,613,614,632],"ul",{},[615,616,617,624,625,628,629,631],"li",{},[618,619,620],"strong",{},[621,622,623],"code",{},"main"," is your currently released code, what you would find in production. (In the original 2010 model this branch was called ",[621,626,627],{},"master","; modern repos default to ",[621,630,623],{},", and that is what I will use throughout.)",[615,633,634,639],{},[618,635,636],{},[621,637,638],{},"develop"," is the integration branch where finished work collects between releases.",[573,641,642],{},"On top of those two, you create short-lived supporting branches as you need them.",[612,644,645,656,667],{},[615,646,647,652,653,655],{},[618,648,649],{},[621,650,651],{},"feature\u002F*"," branches come off ",[621,654,638],{}," for each new piece of work.",[615,657,658,663,664,666],{},[618,659,660],{},[621,661,662],{},"release\u002F*"," branches freeze ",[621,665,638],{}," so you can harden a version before shipping it.",[615,668,669,652,674,676],{},[618,670,671],{},[621,672,673],{},"hotfix\u002F*",[621,675,623],{}," to patch production in a hurry.",[573,678,679,680,682,683,685],{},"The golden rule: you never commit directly to ",[621,681,623],{}," or ",[621,684,638],{},". Everything arrives through a supporting branch.",[577,687,689],{"id":688},"setting-up-the-project","Setting up the project",[573,691,692,693,695],{},"The best way to learn this is by doing, so let's set up a fresh repository. Inside your project directory, create the first commit on ",[621,694,623],{}," and push it up.",[697,698,703],"pre",{"className":699,"code":700,"language":701,"meta":702,"style":702},"language-bash shiki shiki-themes github-dark github-dark","echo \"# Git Flow Example\" >> README.md\ngit init\ngit add README.md\ngit commit -m \"Initial commit\"\ngit remote add origin git@github.com:frankperez87\u002Fgitflow-example.git\ngit push -u origin main\n","bash","",[621,704,705,724,732,741,754,769],{"__ignoreMap":702},[706,707,709,713,717,721],"span",{"class":708,"line":73},"line",[706,710,712],{"class":711},"s8ozJ","echo",[706,714,716],{"class":715},"s4wv1"," \"# Git Flow Example\"",[706,718,720],{"class":719},"sOPea"," >>",[706,722,723],{"class":715}," README.md\n",[706,725,726,729],{"class":708,"line":44},[706,727,15],{"class":728},"sFR8T",[706,730,731],{"class":715}," init\n",[706,733,734,736,739],{"class":708,"line":102},[706,735,15],{"class":728},[706,737,738],{"class":715}," add",[706,740,723],{"class":715},[706,742,743,745,748,751],{"class":708,"line":13},[706,744,15],{"class":728},[706,746,747],{"class":715}," commit",[706,749,750],{"class":711}," -m",[706,752,753],{"class":715}," \"Initial commit\"\n",[706,755,756,758,761,763,766],{"class":708,"line":61},[706,757,15],{"class":728},[706,759,760],{"class":715}," remote",[706,762,738],{"class":715},[706,764,765],{"class":715}," origin",[706,767,768],{"class":715}," git@github.com:frankperez87\u002Fgitflow-example.git\n",[706,770,771,773,776,779,781],{"class":708,"line":46},[706,772,15],{"class":728},[706,774,775],{"class":715}," push",[706,777,778],{"class":711}," -u",[706,780,765],{"class":715},[706,782,783],{"class":715}," main\n",[573,785,786,787,789],{},"That initial commit is the one exception to the never-touch-main rule; we are just bootstrapping the repo. From here on, ",[621,788,623],{}," only changes through releases and hotfixes.",[573,791,792,793,795],{},"Next, create the ",[621,794,638],{}," branch and track it remotely. This is where features will land.",[697,797,799],{"className":699,"code":798,"language":701,"meta":702,"style":702},"git branch develop\ngit push -u origin develop\n",[621,800,801,811],{"__ignoreMap":702},[706,802,803,805,808],{"class":708,"line":73},[706,804,15],{"class":728},[706,806,807],{"class":715}," branch",[706,809,810],{"class":715}," develop\n",[706,812,813,815,817,819,821],{"class":708,"line":44},[706,814,15],{"class":728},[706,816,775],{"class":715},[706,818,778],{"class":711},[706,820,765],{"class":715},[706,822,810],{"class":715},[577,824,826],{"id":825},"feature-branches","Feature branches",[573,828,829,830,832,833,836],{},"Every new piece of work is a feature, unless it is an urgent production fix (that is a hotfix, which we will get to). Let's add a contributing guide. We branch off ",[621,831,638],{}," and prefix the branch with ",[621,834,835],{},"feature\u002F",".",[697,838,840],{"className":699,"code":839,"language":701,"meta":702,"style":702},"git checkout -b feature\u002Fcontributing develop\n",[621,841,842],{"__ignoreMap":702},[706,843,844,846,849,852,855],{"class":708,"line":73},[706,845,15],{"class":728},[706,847,848],{"class":715}," checkout",[706,850,851],{"class":711}," -b",[706,853,854],{"class":715}," feature\u002Fcontributing",[706,856,810],{"class":715},[573,858,859],{},"Now make the change. Keep it small and real.",[697,861,863],{"className":699,"code":862,"language":701,"meta":702,"style":702},"echo \"# Contributing\" >> CONTRIBUTING.md\necho \"Open a pull request against develop and keep changes focused.\" >> CONTRIBUTING.md\ngit add CONTRIBUTING.md\ngit commit -m \"Add contributing guide\"\n",[621,864,865,877,888,896],{"__ignoreMap":702},[706,866,867,869,872,874],{"class":708,"line":73},[706,868,712],{"class":711},[706,870,871],{"class":715}," \"# Contributing\"",[706,873,720],{"class":719},[706,875,876],{"class":715}," CONTRIBUTING.md\n",[706,878,879,881,884,886],{"class":708,"line":44},[706,880,712],{"class":711},[706,882,883],{"class":715}," \"Open a pull request against develop and keep changes focused.\"",[706,885,720],{"class":719},[706,887,876],{"class":715},[706,889,890,892,894],{"class":708,"line":102},[706,891,15],{"class":728},[706,893,738],{"class":715},[706,895,876],{"class":715},[706,897,898,900,902,904],{"class":708,"line":13},[706,899,15],{"class":728},[706,901,747],{"class":715},[706,903,750],{"class":711},[706,905,906],{"class":715}," \"Add contributing guide\"\n",[908,909,910],"blockquote",{},[573,911,912,913,916],{},"You can also name the branch ",[621,914,915],{},"feature-contributing"," with a dash instead of a slash. Both are fine; just pick one convention and stick to it.",[573,918,919,920,922],{},"With the feature done, merge it back into ",[621,921,638],{}," and delete the branch, since it has served its purpose.",[697,924,926],{"className":699,"code":925,"language":701,"meta":702,"style":702},"git checkout develop\ngit merge feature\u002Fcontributing\ngit branch -d feature\u002Fcontributing\n",[621,927,928,936,946],{"__ignoreMap":702},[706,929,930,932,934],{"class":708,"line":73},[706,931,15],{"class":728},[706,933,848],{"class":715},[706,935,810],{"class":715},[706,937,938,940,943],{"class":708,"line":44},[706,939,15],{"class":728},[706,941,942],{"class":715}," merge",[706,944,945],{"class":715}," feature\u002Fcontributing\n",[706,947,948,950,952,955],{"class":708,"line":102},[706,949,15],{"class":728},[706,951,807],{"class":715},[706,953,954],{"class":711}," -d",[706,956,945],{"class":715},[577,958,960],{"id":959},"release-branches","Release branches",[573,962,963,964,966,967,970,971,973],{},"When ",[621,965,638],{}," has enough finished work to ship, you cut a release branch. Release branches are prefixed with ",[621,968,969],{},"release\u002F"," followed by the version number. This freezes a snapshot of ",[621,972,638],{}," so you can do final hardening (version bumps, last-minute fixes, changelog) without blocking new feature work.",[697,975,977],{"className":699,"code":976,"language":701,"meta":702,"style":702},"git checkout -b release\u002F0.1.0 develop\necho \"Version 0.1.0\" >> CHANGELOG.md\ngit add CHANGELOG.md\ngit commit -m \"Prepare 0.1.0 release\"\n",[621,978,979,992,1004,1012],{"__ignoreMap":702},[706,980,981,983,985,987,990],{"class":708,"line":73},[706,982,15],{"class":728},[706,984,848],{"class":715},[706,986,851],{"class":711},[706,988,989],{"class":715}," release\u002F0.1.0",[706,991,810],{"class":715},[706,993,994,996,999,1001],{"class":708,"line":44},[706,995,712],{"class":711},[706,997,998],{"class":715}," \"Version 0.1.0\"",[706,1000,720],{"class":719},[706,1002,1003],{"class":715}," CHANGELOG.md\n",[706,1005,1006,1008,1010],{"class":708,"line":102},[706,1007,15],{"class":728},[706,1009,738],{"class":715},[706,1011,1003],{"class":715},[706,1013,1014,1016,1018,1020],{"class":708,"line":13},[706,1015,15],{"class":728},[706,1017,747],{"class":715},[706,1019,750],{"class":711},[706,1021,1022],{"class":715}," \"Prepare 0.1.0 release\"\n",[573,1024,1025,1026,1028],{},"When the release is ready, merge it into ",[621,1027,623],{},", then tag that commit with the version.",[697,1030,1032],{"className":699,"code":1031,"language":701,"meta":702,"style":702},"git checkout main\ngit merge release\u002F0.1.0\ngit tag -a v0.1.0 -m \"Release 0.1.0\"\ngit push origin main v0.1.0\n",[621,1033,1034,1042,1051,1069],{"__ignoreMap":702},[706,1035,1036,1038,1040],{"class":708,"line":73},[706,1037,15],{"class":728},[706,1039,848],{"class":715},[706,1041,783],{"class":715},[706,1043,1044,1046,1048],{"class":708,"line":44},[706,1045,15],{"class":728},[706,1047,942],{"class":715},[706,1049,1050],{"class":715}," release\u002F0.1.0\n",[706,1052,1053,1055,1058,1061,1064,1066],{"class":708,"line":102},[706,1054,15],{"class":728},[706,1056,1057],{"class":715}," tag",[706,1059,1060],{"class":711}," -a",[706,1062,1063],{"class":715}," v0.1.0",[706,1065,750],{"class":711},[706,1067,1068],{"class":715}," \"Release 0.1.0\"\n",[706,1070,1071,1073,1075,1077,1080],{"class":708,"line":13},[706,1072,15],{"class":728},[706,1074,775],{"class":715},[706,1076,765],{"class":715},[706,1078,1079],{"class":715}," main",[706,1081,1082],{"class":715}," v0.1.0\n",[573,1084,1085,1086,1088,1089,1091,1092,1094],{},"Here is the step people forget: you also merge the release back into ",[621,1087,638],{},". Any fixes or version bumps you made on the release branch happened off ",[621,1090,638],{},"'s line, so merging them back keeps ",[621,1093,638],{}," from falling behind production.",[697,1096,1098],{"className":699,"code":1097,"language":701,"meta":702,"style":702},"git checkout develop\ngit merge release\u002F0.1.0\ngit push\ngit branch -d release\u002F0.1.0\n",[621,1099,1100,1108,1116,1123],{"__ignoreMap":702},[706,1101,1102,1104,1106],{"class":708,"line":73},[706,1103,15],{"class":728},[706,1105,848],{"class":715},[706,1107,810],{"class":715},[706,1109,1110,1112,1114],{"class":708,"line":44},[706,1111,15],{"class":728},[706,1113,942],{"class":715},[706,1115,1050],{"class":715},[706,1117,1118,1120],{"class":708,"line":102},[706,1119,15],{"class":728},[706,1121,1122],{"class":715}," push\n",[706,1124,1125,1127,1129,1131],{"class":708,"line":13},[706,1126,15],{"class":728},[706,1128,807],{"class":715},[706,1130,954],{"class":711},[706,1132,1050],{"class":715},[577,1134,1136],{"id":1135},"hotfix-branches","Hotfix branches",[573,1138,1139,1140,1142,1143,1145],{},"Now suppose a user finds a bug in production that cannot wait for the next release. A hotfix branches straight off ",[621,1141,623],{}," (not ",[621,1144,638],{},"), because you want to patch exactly what is live.",[697,1147,1149],{"className":699,"code":1148,"language":701,"meta":702,"style":702},"git checkout -b hotfix\u002Flogin-typo main\n",[621,1150,1151],{"__ignoreMap":702},[706,1152,1153,1155,1157,1159,1162],{"class":708,"line":73},[706,1154,15],{"class":728},[706,1156,848],{"class":715},[706,1158,851],{"class":711},[706,1160,1161],{"class":715}," hotfix\u002Flogin-typo",[706,1163,783],{"class":715},[573,1165,1166],{},"Make the smallest change that fixes the problem and commit it.",[697,1168,1170],{"className":699,"code":1169,"language":701,"meta":702,"style":702},"git commit -am \"Fix typo on login button\"\n",[621,1171,1172],{"__ignoreMap":702},[706,1173,1174,1176,1178,1181],{"class":708,"line":73},[706,1175,15],{"class":728},[706,1177,747],{"class":715},[706,1179,1180],{"class":711}," -am",[706,1182,1183],{"class":715}," \"Fix typo on login button\"\n",[573,1185,1186,1187,1190,1191,1193,1194,1196,1197,1199,1200,1203,1204,836],{},"Just like a release, a hotfix merges into ",[618,1188,1189],{},"both"," ",[621,1192,623],{}," and ",[621,1195,638],{}," so the fix is not lost, and the new version gets tagged on ",[621,1198,623],{},". A bug fix is a backward-compatible change, so it bumps the PATCH number: ",[621,1201,1202],{},"0.1.0"," becomes ",[621,1205,1206],{},"0.1.1",[697,1208,1210],{"className":699,"code":1209,"language":701,"meta":702,"style":702},"git checkout main\ngit merge hotfix\u002Flogin-typo\ngit tag -a v0.1.1 -m \"Hotfix: login button typo\"\ngit push origin main v0.1.1\n\ngit checkout develop\ngit merge hotfix\u002Flogin-typo\ngit push\n\ngit branch -d hotfix\u002Flogin-typo\n",[621,1211,1212,1220,1229,1245,1258,1263,1271,1279,1286,1291],{"__ignoreMap":702},[706,1213,1214,1216,1218],{"class":708,"line":73},[706,1215,15],{"class":728},[706,1217,848],{"class":715},[706,1219,783],{"class":715},[706,1221,1222,1224,1226],{"class":708,"line":44},[706,1223,15],{"class":728},[706,1225,942],{"class":715},[706,1227,1228],{"class":715}," hotfix\u002Flogin-typo\n",[706,1230,1231,1233,1235,1237,1240,1242],{"class":708,"line":102},[706,1232,15],{"class":728},[706,1234,1057],{"class":715},[706,1236,1060],{"class":711},[706,1238,1239],{"class":715}," v0.1.1",[706,1241,750],{"class":711},[706,1243,1244],{"class":715}," \"Hotfix: login button typo\"\n",[706,1246,1247,1249,1251,1253,1255],{"class":708,"line":13},[706,1248,15],{"class":728},[706,1250,775],{"class":715},[706,1252,765],{"class":715},[706,1254,1079],{"class":715},[706,1256,1257],{"class":715}," v0.1.1\n",[706,1259,1260],{"class":708,"line":61},[706,1261,1262],{"emptyLinePlaceholder":103},"\n",[706,1264,1265,1267,1269],{"class":708,"line":46},[706,1266,15],{"class":728},[706,1268,848],{"class":715},[706,1270,810],{"class":715},[706,1272,1273,1275,1277],{"class":708,"line":10},[706,1274,15],{"class":728},[706,1276,942],{"class":715},[706,1278,1228],{"class":715},[706,1280,1282,1284],{"class":708,"line":1281},8,[706,1283,15],{"class":728},[706,1285,1122],{"class":715},[706,1287,1289],{"class":708,"line":1288},9,[706,1290,1262],{"emptyLinePlaceholder":103},[706,1292,1294,1296,1298,1300],{"class":708,"line":1293},10,[706,1295,15],{"class":728},[706,1297,807],{"class":715},[706,1299,954],{"class":711},[706,1301,1228],{"class":715},[577,1303,1305],{"id":1304},"a-quick-word-on-versioning","A quick word on versioning",[573,1307,1308,1309,1315,1316,1319],{},"Those tags are not arbitrary. Git Flow pairs naturally with ",[591,1310,1314],{"href":1311,"rel":1312},"https:\u002F\u002Fsemver.org\u002F",[1313],"nofollow","semantic versioning",", where a version reads ",[621,1317,1318],{},"MAJOR.MINOR.PATCH",":",[612,1321,1322,1328,1338],{},[615,1323,1324,1327],{},[618,1325,1326],{},"MAJOR"," for a breaking change.",[615,1329,1330,1333,1334,1337],{},[618,1331,1332],{},"MINOR"," for new, backward-compatible functionality (your next feature release would be ",[621,1335,1336],{},"v0.2.0",").",[615,1339,1340,1343,1344,1337],{},[618,1341,1342],{},"PATCH"," for a backward-compatible bug fix (the hotfix above, ",[621,1345,1346],{},"v0.1.1",[573,1348,1349,1350,1352],{},"Tag every release on ",[621,1351,623],{}," and your team, along with your users, can always check out exactly what shipped and when.",[577,1354,1356],{"id":1355},"the-git-flow-cli","The git flow CLI",[573,1358,1359,1360,1363],{},"You do not have to type all of those merges and tags by hand. The ",[621,1361,1362],{},"git flow"," extension wraps the whole model into a handful of commands.",[697,1365,1367],{"className":699,"code":1366,"language":701,"meta":702,"style":702},"git flow init                          # set up main, develop and the branch prefixes\ngit flow feature start contributing    # branch off develop\ngit flow feature finish contributing   # merge back into develop, delete the branch\ngit flow release start 0.1.0           # branch off develop\ngit flow release finish 0.1.0          # merge to main and develop, tag main\ngit flow hotfix start 0.1.1            # branch off main\ngit flow hotfix finish 0.1.1           # merge to main and develop, tag main\n",[621,1368,1369,1383,1401,1417,1434,1449,1466],{"__ignoreMap":702},[706,1370,1371,1373,1376,1379],{"class":708,"line":73},[706,1372,15],{"class":728},[706,1374,1375],{"class":715}," flow",[706,1377,1378],{"class":715}," init",[706,1380,1382],{"class":1381},"sJ8bj","                          # set up main, develop and the branch prefixes\n",[706,1384,1385,1387,1389,1392,1395,1398],{"class":708,"line":44},[706,1386,15],{"class":728},[706,1388,1375],{"class":715},[706,1390,1391],{"class":715}," feature",[706,1393,1394],{"class":715}," start",[706,1396,1397],{"class":715}," contributing",[706,1399,1400],{"class":1381},"    # branch off develop\n",[706,1402,1403,1405,1407,1409,1412,1414],{"class":708,"line":102},[706,1404,15],{"class":728},[706,1406,1375],{"class":715},[706,1408,1391],{"class":715},[706,1410,1411],{"class":715}," finish",[706,1413,1397],{"class":715},[706,1415,1416],{"class":1381},"   # merge back into develop, delete the branch\n",[706,1418,1419,1421,1423,1426,1428,1431],{"class":708,"line":13},[706,1420,15],{"class":728},[706,1422,1375],{"class":715},[706,1424,1425],{"class":715}," release",[706,1427,1394],{"class":715},[706,1429,1430],{"class":711}," 0.1.0",[706,1432,1433],{"class":1381},"           # branch off develop\n",[706,1435,1436,1438,1440,1442,1444,1446],{"class":708,"line":61},[706,1437,15],{"class":728},[706,1439,1375],{"class":715},[706,1441,1425],{"class":715},[706,1443,1411],{"class":715},[706,1445,1430],{"class":711},[706,1447,1448],{"class":1381},"          # merge to main and develop, tag main\n",[706,1450,1451,1453,1455,1458,1460,1463],{"class":708,"line":46},[706,1452,15],{"class":728},[706,1454,1375],{"class":715},[706,1456,1457],{"class":715}," hotfix",[706,1459,1394],{"class":715},[706,1461,1462],{"class":711}," 0.1.1",[706,1464,1465],{"class":1381},"            # branch off main\n",[706,1467,1468,1470,1472,1474,1476,1478],{"class":708,"line":10},[706,1469,15],{"class":728},[706,1471,1375],{"class":715},[706,1473,1457],{"class":715},[706,1475,1411],{"class":715},[706,1477,1462],{"class":711},[706,1479,1480],{"class":1381},"           # merge to main and develop, tag main\n",[573,1482,1483,1484,1487,1488,1491,1492,1494],{},"It is doing exactly the merges and tags you just learned, which is why it is worth understanding the manual flow first. One heads-up for 2026: the original ",[621,1485,1486],{},"nvie\u002Fgitflow"," extension was archived in October 2025 (it now points to a successor called git-flow-next), and the long-popular ",[621,1489,1490],{},"gitflow-avh"," fork was archived back in 2023. The model is the same either way, so I lean on the plain ",[621,1493,15],{}," commands above and treat the CLI as optional sugar.",[577,1496,1498],{"id":1497},"wrapping-up","Wrapping up",[573,1500,1501,1502,1504],{},"That is Git Flow end to end: two long-lived branches, supporting branches for features, releases and hotfixes, and a tag on ",[621,1503,623],{}," for every version. The structure shines when you ship versioned software on a schedule and have to maintain more than one release at a time.",[573,1506,1507,1508,1510],{},"If that does not sound like your project, do not force it. The real win is that your whole team agrees on how branches are named, when things merge, and how releases get tagged. For a continuously deployed web app, that agreement usually looks like ",[591,1509,594],{"href":593}," instead. Either way, pick one, write it down, and get everyone using it.",[1512,1513,1514],"style",{},"html pre.shiki code .s8ozJ, html code.shiki .s8ozJ{--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .s4wv1, html code.shiki .s4wv1{--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .sOPea, html code.shiki .sOPea{--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .sFR8T, html code.shiki .sFR8T{--shiki-default:#B392F0;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":702,"searchDepth":44,"depth":44,"links":1516},[1517,1518,1519,1520,1521,1522,1523,1524,1525],{"id":579,"depth":44,"text":580},{"id":606,"depth":44,"text":607},{"id":688,"depth":44,"text":689},{"id":825,"depth":44,"text":826},{"id":959,"depth":44,"text":960},{"id":1135,"depth":44,"text":1136},{"id":1304,"depth":44,"text":1305},{"id":1355,"depth":44,"text":1356},{"id":1497,"depth":44,"text":1498},{"id":13,"name":14,"slug":15,"hue":16},"md",{},{"title":136,"description":575},"posts\u002Fimprove-your-git-workflow-with-git-flow",[15,22],[1533,1534],{"name":19,"slug":15},{"name":21,"slug":22},"O5ShS0GHY3UuUSOveNIN6_RCKEi7BQk-fI4A7VyLsZg",1781454357467]