<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>merge on Digi Hunch</title><link>https://static.digihunch.com/tag/merge/</link><description>Recent content in merge on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Tue, 21 Jan 2025 20:49:35 -0500</lastBuildDate><atom:link href="https://static.digihunch.com/tag/merge/index.xml" rel="self" type="application/rss+xml"/><item><title>Git Branching Strategy</title><link>https://static.digihunch.com/2021/03/git-branching-strategy/</link><pubDate>Sun, 07 Mar 2021 19:20:42 -0400</pubDate><guid>https://static.digihunch.com/2021/03/git-branching-strategy/</guid><description>&lt;p class="wp-block-paragraph"&gt;I have been in two discussions about &lt;a href="https://static.digihunch.com/2019/06/git-explained-1-of-2/"&gt;Git&lt;/a&gt; branching strategy in different organizations. Too many concepts! So I open this post to jot down the lineage of common branching strategies to help organizations develop their branching policies. In terms of reference, there is a lot from Atlassian documentation. In addition, I also find this one &lt;a class="rank-math-link" href="https://medium.com/factualopinions/branching-models-in-a-nutshell-bf24ea1d888a"&gt;article &lt;/a&gt;a good resource.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-centralized-workflow-no-branching"&gt;Centralized workflow (no branching)&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In &lt;a href="https://www.atlassian.com/git/tutorials/comparing-workflows#centralized-workflow" class="rank-math-link"&gt;Centralized Workflow&lt;/a&gt;, the team uses a central repository to serve as the single-point-of-entry for all changes to the project. The default branch is master, and all changes are committed to this branch. This workflow does not require any other branches beside master. Local changes may conflict with upstream commits, and conflict needs to be resolved.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This workflow is usually seen in teams transitioning from SVN, with very basic skill level. This workflow may also be adopted in teams working on configuration management instead of source code. Centralized workflow is great for small teams. The conflict resolution process can form a bottleneck as the team scales in size.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-feature-branch-workflow"&gt;Feature Branch Workflow &lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Instead of directly committing on their local master branch, developers create a new branch every time they start work on a new feature. Feature branches should have descriptive names (e.g. issue#112). Feature branches are pushed to the central repository so that they can be shared to other developers without touching any official (master) code. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To get feedback on the new feature branch, create a pull request in a repository management solution (e.g. Bitbucket Cloud, Bitbucket Server). Before merge, you may have to resolve merge conflicts if others have made changes to the master branch of repo. This is to make sure your local master is synchronized with the upstream master. When your pull request is approved and conflict free, you can merge your branch to master branch.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter is-resized"&gt;&lt;img decoding="async" src="https://wac-cdn.atlassian.com/dam/jcr:09308632-38a3-4637-bba2-af2110629d56/07.svg?cdnVersion=1491" alt="Feature Branch Workflow: Merging a feature branch" style="width:549px;height:97px"/&gt;&lt;figcaption class="wp-element-caption"&gt;feature branch workflow&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Git Feature Branch Workflow is a composable workflow that can be leveraged by other high-level Git workflows. Git Feature Branch Workflow is branching model focused, instead of release focused. The Git Feature Branch Workflow can be incorporated into other workflows. The Gitflow, and Git Forking Workflows traditionally use a Git Feature Branch Workflow in regards to their branching models.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-gitflow-workflow"&gt;Gitflow Workflow&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;First &lt;a href="https://nvie.com/posts/a-successful-git-branching-model/"&gt;published&lt;/a&gt; in 2010 by Vincent Driessen. Gitflow defines a strict branching model designed around the project release. This provides a robust framework for managing larger projects. In addition to Feature Branch Workflow, Gitflow workflow assigns very specific roles to different branches and defines how and when they should interact.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Instead of a single master branch, this workflow uses two branches to record the history of the project. The master branch stores the official release history, and the develop branch serves as an integration branch for features. It is also convenient to tag all commits in the master branch with a version number.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This workflow is operated in the following ways:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;A develop branch is created from master&lt;/li&gt;&#10;&lt;li&gt;Feature branches are created from develop. When a feature is complete, with PR reviewed, it is merged into the develop branch. Features branches&lt;/li&gt;&#10;&lt;li&gt;Once develop has acquired enough features for a release (or a predetermined release date is approaching), we fork a release branch off of develop. Creating this branch starts the next release cycle, so new features can be added to develop after this point. On the release branch itself, only bug fixes, documentation generation, and other release-oriented tasks should go in this branch. Once ready to ship, the release branch gets merged into master and tagged with a version number. In addition, it should also be merged back into develop, which may have progressed since the release was initiated.&lt;/li&gt;&#10;&lt;li&gt;Maintenance or hotfix branches are used to quicly patch production releases. Hotfix branches are a lot like release branchs and feature branches except they&amp;#8217;re based on master instead of develop. As soon as the fix is complete, it should be merged into both master and develop (or the current release branch), and master should be tagged with an updated version number. &lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter is-resized"&gt;&lt;img decoding="async" src="https://wac-cdn.atlassian.com/dam/jcr:61ccc620-5249-4338-be66-94d563f2843c/05%20(2).svg?cdnVersion=1491" alt="Git flow workflow - Hotfix Branches" style="width:572px;height:409px"/&gt;&lt;figcaption class="wp-element-caption"&gt;Gitflow workflow&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There is a Git extension named git-flow to provide high-level repository operations for this Workflow, such as start a release, finish a release, start a hotfix, finish a hotfix.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Gitflow is ideally suited for projects that have a scheduled release cycle and for the DevOps best practice of continuous delivery. It ensures that the master branch reflects what is deployed (e.g. in production). However, it is quite &lt;strong&gt;complex&lt;/strong&gt; and have a &lt;strong&gt;steep learning curve&lt;/strong&gt; for organizations. It also runs &lt;strong&gt;long-lived branches&lt;/strong&gt;, which is considered bad from CI/CD perspective. Branches are by definition to isolate and hide changes, whereas &lt;strong&gt;continuous integration &lt;/strong&gt;is about exposing changes early on and frequently. In that sense, the Gitflow branching model and CI/CD are &lt;strong&gt;mutually exclusive&lt;/strong&gt; ideas. &lt;/p&gt;&#10;&lt;blockquote class="wp-block-quote is-style-plain is-layout-flow wp-block-quote-is-layout-flow"&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In 2020, Vincent Driessen added a note at the beginning of his &lt;a href="https://nvie.com/posts/a-successful-git-branching-model/"&gt;article&lt;/a&gt; on Gitflow:&lt;/p&gt;&#10;&lt;cite&gt;If your team is doing continuous delivery of software, I would suggest to adopt a much simpler workflow (like GitHub flow) instead of trying to shoehorn git-flow into your team.&lt;br&gt;If, however, you are building software that is explicitly versioned, or if you need to support multiple versions of your software in the wild, then git-flow may still be as good of a fit to your team as it has been to people in the last 10 years.&lt;/cite&gt;&lt;/blockquote&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Driessen&amp;#8217;s notes also points to some simple alternatives. On the other hand, the &lt;a href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow"&gt;Atlassian tutorial&lt;/a&gt; on Gitflow has described Gitflow workflow as a legacy (since Aug 2021 based on web &lt;a href="https://web.archive.org/web/20210802194504/https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow"&gt;archive&lt;/a&gt;). It points out at the beginning that Gitflow has fallen in popularity in favor of&amp;nbsp;&lt;a href="https://www.atlassian.com/continuous-delivery/continuous-integration/trunk-based-development"&gt;trunk-based workflows&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-github-flow-trunk-based-development-tbd-and-gitlab-flow"&gt;GitHub flow, Trunk-based development (TBD) and GitLab flow&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;It is operationally expensive to manage multiple mainlines in Git flow workflow, with both source control and release in the picture. Some simple alternatives have been evolved, with single mainline, for example, &lt;strong&gt;GitHub flow&lt;/strong&gt; and &lt;strong&gt;trunk-based development&lt;/strong&gt;. They differ in where the release is performed from. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the &lt;a href="https://guides.github.com/introduction/flow/" class="rank-math-link"&gt;GitHub flow&lt;/a&gt;, release is performed from branch before being merged back to master (trunk).&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://trunkbaseddevelopment.com/alternative-branching-models/githubflow1.png" alt=""/&gt;&lt;figcaption class="wp-element-caption"&gt;GitHub flow&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In &lt;a href="https://www.atlassian.com/continuous-delivery/continuous-integration/trunk-based-development" class="rank-math-link"&gt;trunk-based development&lt;/a&gt;, release is not performed until the feature branch has been merged to the trunk (master). In trunk-based development, feature branches are supposed to be short-lived. It is a common practice among DevOps teams, since it streamlines merging and integration phases.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://trunkbaseddevelopment.com/5-min-overview/trunk_pr.png" alt=""/&gt;&lt;figcaption class="wp-element-caption"&gt;Trunk-based development&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Trunk-based development has gained some momentum in recent years, due to its DevOps friendliness. &lt;a href="https://trunkbaseddevelopment.com/" class="rank-math-link"&gt;This &lt;/a&gt;is a website that advocates it and here&amp;#8217;s a DZone &lt;a href="https://dzone.com/articles/why-i-prefer-trunk-based-development-over-feature" class="rank-math-link"&gt;article &lt;/a&gt;about it.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-gitlab-flow"&gt;Gitlab Flow&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In response to the shortcomings of GitHub flow and Gitflow, Gitlab introduced its own proposal of branching strategy, known as &lt;a href="https://docs.gitlab.com/ee/topics/gitlab_flow.html" class="rank-math-link"&gt;Gitlab flow&lt;/a&gt;. The most distinctive aspect is the environment branches. In Gitlab flow, you run multiple long-lived branches, each of them representing an environment. The typical steps are as follows:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;You create short-lived feature branches, and merge them often to the master.&lt;/li&gt;&#10;&lt;li&gt;Every developer starts from master and targets master. Other branches are merged from previous lower environment branches.&lt;/li&gt;&#10;&lt;li&gt;You can deploy a new version to production, by merging master into the production branch.&lt;/li&gt;&#10;&lt;li&gt;If you need to know what code is in production, you can check out the production branch to see.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="528" height="700" src="https://static.digihunch.com/wp-content/uploads/2023/01/gitlab_flow.png" alt="" class="wp-image-7742" srcset="https://static.digihunch.com/wp-content/uploads/2023/01/gitlab_flow.png 528w, https://static.digihunch.com/wp-content/uploads/2023/01/gitlab_flow-226x300.png 226w" sizes="auto, (max-width: 528px) 100vw, 528px" /&gt;&lt;figcaption class="wp-element-caption"&gt;&lt;strong&gt;Gitlab flow&lt;/strong&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;You only need to work with release branches, if you need to release software code to the outside world. Here are some &lt;a class="rank-math-link" href="https://about.gitlab.com/topics/version-control/what-are-gitlab-flow-best-practices/"&gt;best practices&lt;/a&gt; in GitLab flow.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-forking-workflow"&gt;Forking Workflow&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Forking workflow is fundamentally different. The key steps are as follows:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;A developer &amp;#8216;forks&amp;#8217; an &amp;#8216;official&amp;#8217; server-side repository. This creates their own server-side copy. This is their personal public repository, and no other developer are allowed to push to it.&lt;/li&gt;&#10;&lt;li&gt;The new server-side copy is cloned to their local system. This forms an environment dedicated to this developer.&lt;/li&gt;&#10;&lt;li&gt;With the local clone, developer needs to create the upstream remote manually using &amp;#8220;git remote add upstream&amp;#8221; command. This allows the developer keep the local repository up-to-date as the official project progresses. &lt;/li&gt;&#10;&lt;li&gt;A new local feature branch is created. Developer commits to the new local branch, and pushes to their own copy of repository on server.&lt;/li&gt;&#10;&lt;li&gt;Developer files a pull request from the new branch (in own copy of repository) to the &amp;#8216;official&amp;#8217; repository. The project maintainer knows that an update is ready to be integrated. The PR also serves as a discussion thread.&lt;/li&gt;&#10;&lt;li&gt;The PR gets approved for merge and is merged into the original server-side repository.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This workflow has other names, such as &lt;a href="https://blog.scottlowe.org/2015/01/27/using-fork-branch-git-workflow/" class="rank-math-link"&gt;fork-and-branch workflow&lt;/a&gt;, and is commonly used in GitHub for managing open-source projects. However, this should not be confused with the aforementioned GitHub flow.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-conclusion"&gt;Conclusion&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In order to fully support distributed source control, Git abstract version control problems into concepts such as commit, branch, etc. This makes discussion about Git workflow and branching strategy difficult due to the conceptual hurdles and organization differences. We covered choices of Git branching strategy in this post. As Vincent Driessen commented in his &lt;a class="rank-math-link" href="https://nvie.com/posts/a-successful-git-branching-model/"&gt;original Gitflow posting&lt;/a&gt;, panaceas don&amp;#8217;t exist. We should consider the context (e.g. team size, Git skill level, etc) to determine the best Git branching strategy.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/02/interpret-census-data-from-statistics-canada/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Census Data from Statistics Canada&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/03/intro-to-data-analytics-platform/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Intro to Data Analytics Platform on Azure&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Common local Git operations</title><link>https://static.digihunch.com/2020/04/common-local-git-operations/</link><pubDate>Wed, 08 Apr 2020 11:54:00 -0400</pubDate><guid>https://static.digihunch.com/2020/04/common-local-git-operations/</guid><description>&lt;p class="wp-block-paragraph"&gt;This is a summary of concepts in common Git operations. We will discuss brach, merge, rebase, cherrypick, stash and reset. Then we&amp;#8217;ll discuss pull, fetch, and push.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-commit-branch-and-head"&gt;Commit, Branch and HEAD&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When you run &amp;#8220;git commit&amp;#8221;, the following happens:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Git checksums each subdirectory, and stores them as a tree object (file path and name) and blob object (file content) in Git repository;&lt;/li&gt;&lt;li&gt;Git creates a commit object that has the metadata and a pointer to the root project tree; or if this is not the first commit, the pointer will point to the commit immediately before it&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The operations above should form a chain of commit. It can be a long chain and may diverge into branches. In Git semantics however, a branch is simply a lightweight, movable pointer to one of the commits. The default branch name in Git is master. A Git repository may contain multiple branches and the name master itself does not suggest any privilege. There is also a special pointer called HEAD, which indicates the branch you are currently working on. So branch is essentially a pointer to a commit; HEAD is essentially a pointer to a branch. &amp;#8220;git checkout&amp;#8221; can switch branch that HEAD points to. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-basic-merge"&gt;Basic Merge&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;One type of basic merge simply moves branch pointer from one commit to another (along the same chain) without creating any commit. Here is a diagram before basic merge:&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://git-scm.com/book/en/v2/images/basic-branching-4.png" alt="Hotfix branch based on `master`."/&gt;&lt;figcaption&gt;Before basic merge, Hotfix branch is based on&amp;nbsp;&lt;code&gt;master&lt;/code&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The following command performs basic merge:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git merge hotfix&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Updating f42c576..3a0874c&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Fast-forward&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; index.html | 2 ++&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1 file changed, 2 insertions(+)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then Git simply moves the pointer (named master) forward. There is no divergent work to move together, hence no chance of merge conflict. This type of basic merge is also called &amp;#8220;fast-forward&amp;#8221; merge.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://git-scm.com/book/en/v2/images/basic-branching-5.png" alt="`master` is fast-forwarded to `hotfix`."/&gt;&lt;figcaption&gt;After basic merge, &lt;code&gt;master&lt;/code&gt;&amp;nbsp;is fast-forwarded to&amp;nbsp;&lt;code&gt;hotfix&lt;/code&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The other type of merge involves reconciling divergent work together, which may or may not involve conflict. Suppose this is the commit tree to start with:&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://git-scm.com/book/en/v2/images/basic-merging-1.png" alt="Three snapshots used in a typical merge."/&gt;&lt;figcaption&gt;Three snapshots used in a typical merge&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The following commands perform the merge:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Switched to branch &amp;#39;master&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git merge iss53&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Merge made by the &amp;#39;recursive&amp;#39; strategy.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;index.html | 1 +&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1 file changed, 1 insertion(+)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Instead of just moving the branch pointer forward, Git creates a new snapshot that results from this three-way merge and automatically creates a new commit that points to it. This is referred to as a merge commit, and is special in that it has more than one parent.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://git-scm.com/book/en/v2/images/basic-merging-2.png" alt="A merge commit."/&gt;&lt;figcaption&gt;A merge commit&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now that your work is merged in, you have no further need for the&amp;nbsp;&lt;code&gt;iss53&lt;/code&gt;&amp;nbsp;branch. You can close the issue in your issue-tracking system, and delete the branch:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git branch -d iss53&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;If commits from two respective branches changes the same file in different ways, then there is a merge conflict. In this case, Git cannot just create a merge commit. Instead it asks the user to resolve the conflict first. You have to choose either side of the change, or just merge the content yourself. At this point, if you introduce a change that does not appear in any parent, it is referred to as an evil merge. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Beyond the basic merge, there are more sophisticated merge conflict resolution tools covered in &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging"&gt;advanced merging&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-merge-and-rebase"&gt;Merge and Rebase&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are two ways to integrate changes from one branch to another. Merge and rebase. Suppose your commit chain diverge into a master branch and a feature branch. Merging (from feature to master) takes the content of feature branch and integrate it with master branch. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git merge feature&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;When you rebase a feature branch onto master, you move the base of the feature branch to master branch’s ending point.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout feature&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git rebase master&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;After merge, you are still &lt;span style="text-decoration: underline;"&gt;on the same branch&lt;/span&gt;. The commits from other branch are integrated into the branch that you are already on. There is no change in any existing commits (history). After rebase, your base will be &lt;span style="text-decoration: underline;"&gt;moved to a different branch&lt;/span&gt;, along with the commits that you have made in the previous branch (since the diverge). In other words, by re-playing those commits on a different branch, it changed history.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://miro.medium.com/max/855/1*pzT4KMiZDOFsMOKH-cJjfQ.png" alt=""/&gt;&lt;figcaption&gt;merge vs rebase&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The chart above is stolen from &lt;a href="https://hackernoon.com/git-merge-vs-rebase-whats-the-diff-76413c117333"&gt;this article&lt;/a&gt;, which does a better job explain in detail the difference, pros and cons of merge and rebase. Merge does create a &amp;#8220;merge commit&amp;#8221;, and a git history full of merges can be cluttered. Rebase does not create an extra commit but since it changes the history of a branch, it has impact to other collaborators. It can be done in an interactive way (with -i switch). The golden rules of rebasing is covered in &lt;a href="https://www.atlassian.com/git/tutorials/merging-vs-rebasing"&gt;this&lt;/a&gt; article. One of the principles is that never perform a rebase on a public branch.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="600" height="335" src="https://static.digihunch.com/wp-content/uploads/2020/08/0.gif" alt="" class="wp-image-1196"/&gt;&lt;figcaption&gt;git operations&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h3 class="wp-block-heading" id="h-cherrypick"&gt;Cherrypick&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In a cherrypick operation, the current branch does not change. You simply pick interested commits from other branches to re-apply to your current branch. You may pick a single or a series of commits from other branch. These commits are not &amp;#8220;moved&amp;#8221; to your current branch. They remain intact. They are just re-played as new commit to current branch. Unlike rebase, there is no re-writing of history, hence not as dangerous.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-reset-and-stash"&gt;Reset and Stash&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Suppose you are working on a part of a project and it starts getting messy. There has been an urgent bug that needs your immediate attention. It is time to save your changes and switch branches. If you are okay to give up your uncommitted work, you may perform a reset, in one of the three modes covered in a &lt;a href="https://static.digihunch.com/2019/06/git-explained-1-of-2/"&gt;previous article&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;But most likely, you don’t want to do a commit of half-done work. The solution is git stash. Stashing is handy if you need to quickly switch context and work on something else but you&amp;#8217;re mid-way through a code change and aren&amp;#8217;t quite ready to commit. In the most basic workflow, you need to run this command to save your uncommitted (but staged) work. As soon as you stash your change, the working directory is clean with all uncommitted local changes saved elsewhere. You can perform any other Git operations, such as change branch. When you&amp;#8217;re ready to resume, you may pop the stash. Here is an example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git add .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git stash&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout correctbranch&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git stash pop&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Instead of pop, you can also use apply to keep the changes in working directory. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git stash apply&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;More details are on &lt;a href="https://www.atlassian.com/git/tutorials/saving-changes/git-stash"&gt;this page&lt;/a&gt; from Bitbutket.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-fetch-and-pull"&gt;Fetch and Pull&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A git fetch simply downloads blob data from remote so the .git directory comes in sync with the server. It does not attempt to update the local working directory. If there is staged or uncommitted local changes, fetch will not impact them. &lt;strong&gt;A git pull is essentially git fetch followed by git merge&lt;/strong&gt;. In addition to downloading blob data, it also updates local working directory. Therefore, there is a chance of merge conflict when the same file has been modified locally. Git will usually guide you through the merge conflict by flagging the conflict area in the file and let you decide the survival changes. For example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#! /usr/bin/env ruby&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;def hello&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;lt; HEAD&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#39;hola world&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=======&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#39;hello mundo&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; mundo&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;end&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hello&lt;span style="color:#f92672"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;You will be prompted in an editor session to reconcile the conflict. Once the file is saved, you will also need to do a &amp;#8220;merge commit&amp;#8221;, before you can pull again.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-push"&gt;Push&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Git push is the opposite of pull, where you merge local branch to the remote. (There is no opposite of fetch because there is no point to merge to remote without updating working directory, no collaborator works on the working directory on the server after all). If the local branch has fallen out of sync with the remote, there is a chance of merge error during git push. To minimize the chance of a merge during push, we can run a git pull before and reconcile any potential conflict locally. This is known as a pre-merge.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Visualizer&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I came across a great visualizer of commit chain &lt;a href="https://git-school.github.io/visualizing-git/"&gt;here&lt;/a&gt;. In the command panel type some git command and it will print the commit graph for you&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/03/ntlm-and-kerberos/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;NTLM and Kerberos protocols&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/04/how-memory-usage-adds-up-in-linux/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;How memory usage adds up in Linux&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>