{"id":89209,"date":"2020-12-07T13:03:15","date_gmt":"2020-12-07T13:03:15","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=89209"},"modified":"2021-04-27T13:35:08","modified_gmt":"2021-04-27T13:35:08","slug":"feature-branches-and-pull-requests-with-git-to-manage-conflicts","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/devops\/database-devops\/feature-branches-and-pull-requests-with-git-to-manage-conflicts\/","title":{"rendered":"Feature branches and pull requests with Git to manage conflicts"},"content":{"rendered":"<p>I\u2019ve recently fielded two questions from different customers regarding how to best work as a team committing database changes to Git.<\/p>\n<p>While there are a wide variety of branching models which work well for databases with Git &#8212; <a href=\"https:\/\/littlekendra.com\/2020\/01\/10\/why-i-like-the-release-flow-branching-strategy-with-git-for-database-devops\/\">Release Flow<\/a>, <a href=\"https:\/\/www.atlassian.com\/git\/tutorials\/comparing-workflows\/gitflow-workflow\">GitFlow<\/a>, or <a href=\"https:\/\/www.red-gate.com\/simple-talk\/blogs\/reordering-deployments-in-database-devops\/#env-branches\">environment-specific branching models<\/a> \u2013 almost every successful Git workflow emphasizes two things:<\/p>\n<ul>\n<li>Using feature branches (also known as topic branches) for the initial development of code<\/li>\n<li>Using Pull Requests to merge changes from feature branches into a mainline or shared code branch<\/li>\n<\/ul>\n<p>These two patterns are very common because Git encourages workflows that branch and merge often, even multiple times in a day. (To learn more about branching, read <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Branching-Branches-in-a-Nutshell\" target=\"_blank\" rel=\"noopener\">Branching in a Nutshell<\/a>.)<\/p>\n<p>In other words, Git is a powerful VCS and has very complex functionality at hand. In my experience, becoming familiar with patterns of branching, merging, and conflict resolution have helped make Git\u2019s complexity easier to understand and have helped me feel like I\u2019m working <em>with<\/em> Git \u2013 rather than constantly fighting <em>against<\/em> Git.<\/p>\n<p>A pleasant side effect is that this also makes working with Git more fun: I\u2019m able to work more frequently with common commands that work predictably and focus more on my work, rather than resolving an unexpected error.<\/p>\n<h2>What does this workflow look like?<\/h2>\n<p>If you\u2019re not an experienced Git user, this probably sounds quite abstract. Here is a diagram of an example workflow which may help you visualize it. This workflow diagram shows a workflow with time flowing from left to right:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-89210\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/12\/branching-diagram.png\" alt=\"Branching diagram\" width=\"1109\" height=\"447\" \/><\/p>\n<p>In this workflow, there is a <em>main<\/em> branch. The main branch represents a mainline of code \u2013 it could be named <em>master<\/em>; it could be named <em>trunk<\/em>; the naming is up to your preferences. In this example, everything merged into the <em>main<\/em> branch is expected to be code that has been reviewed and is considered to be ready to be deployable to a QA environment via automation.<\/p>\n<p>Let\u2019s say that our developers are working with the free Git client in VSCode and are using a tool like Redgate\u2019s <a href=\"https:\/\/www.red-gate.com\/products\/sql-development\/sql-source-control\/\">SQL Source Control<\/a>, <a href=\"https:\/\/documentation.red-gate.com\/rgd1\/oracle\/redgate-change-control\">Redgate Change Control<\/a>, or <a href=\"https:\/\/documentation.red-gate.com\/sca\">SQL Change Automation<\/a> to script their database changes and manage the state of their development databases. (I\u2019m mentioning specific Redgate tools here because I\u2019m very familiar with how they work \u2013 if you\u2019re using other tools, they may follow similar flows as this. A lot depends on how the tool has been designed, how much of a Git client is implemented inside the tool, the types of files it uses, and the naming conventions of the files.)<\/p>\n<p>A developer, Amy, has used VSCode\u2019s Git client to create a branch named feature1 off main. Here\u2019s how feature1 progresses:<\/p>\n<ul>\n<li>Amy works in a dedicated development database and uses their database development tool of choice (SQL Source Control, Redgate Change Control, SQL Change Automation) to generate database code and commit it to their local clone of the Git repository.<\/li>\n<li>After the second commit to feature1, Amy merges from the main branch into feature1 to check if any other commits have been made to main since the feature1 branch was created. In this case, there have been no commits to merge in.<\/li>\n<li>When Amy believes their feature is complete, they do a final code generation and commit with their database development tool, then push the feature1 branch to the upstream repository.<\/li>\n<li>Amy then creates a Pull Request in the upstream Git repository to merge feature1 into main.<\/li>\n<li>The Pull Request process may run a build against the code and automatically add the appropriate reviewers. It also supports discussion and interaction about the change.<\/li>\n<li>The Pull Request is approved and completed, resulting in Amy\u2019s changes in feature1 being merged into main.<\/li>\n<\/ul>\n<p>Another developer, Beth, creates the branch feature2 from main using VSCode\u2019s Git client.<\/p>\n<p>Beth happens to do this a short time after Amy created the feature1 branch, but <em>before<\/em> Amy used a Pull Request to merge her changes back into main.<\/p>\n<ul>\n<li>By the time Beth decides that feature2 is ready to be shared, Amy already merged feature1 back into main via Pull Request.<\/li>\n<li>Beth uses the Git client in VSCode to pull down main and see if anything has changed in it recently \u2013 and she finds that there have been changes.<\/li>\n<li>Beth merges the main branch into feature2 and discovers that some of the files she changed when generating and committing code with her database tool was also changed in main.<\/li>\n<li>This is presented as a conflict by the Git client in VSCode. The Git client asks Amy to resolve it for the feature 2 branch.<\/li>\n<li>Amy has three choices for each file: she may decide to keep only her own changes which she made to feature2, take only the \u201cincoming\u201d changes (from main), or accept both and combine them. Amy may additionally make changes to the files involved in the conflict, such as fixing up commas or making other manual edits.<\/li>\n<li>After deciding how to merge the changes (let\u2019s say they are compatible changes and she decides to combine them), Amy saves the modified files in VSCode. She then stages (\u201cadds\u201d) them and commits the changes into the feature2 branch. This commit concludes the merge process.<\/li>\n<li>At this point, it\u2019s useful for Amy to validate that the merge has resulted in valid SQL and to update her development database with any changes she has accepted. She can do this by opening her database development tool and \u201capply\u201d updates to her development database.<\/li>\n<li>When ready to merge changes into main, Amy pushes her commits upstream in the feature1 branch, and follows the same Pull Request workflow described above to merge changes into main.<\/li>\n<\/ul>\n<p><strong>Q: Can the developers work in a shared database?<\/strong><\/p>\n<p>In this workflow, developers are working in isolated feature branches and sharing changes by merging. What if each developer doesn\u2019t have their own copy of the database to associate with their feature branch?<\/p>\n<p>First off, dedicated development databases solve many problems and promote better quality code. Troy Hunt outlines why this is the case in his post, <a href=\"https:\/\/www.troyhunt.com\/unnecessary-evil-of-shared-development\/\">The unnecessary evil of the shared development database from 2011<\/a>. Although this post is a classic, it\u2019s still highly relevant, and the only thing that has changed is that SQL Server Developer Edition is now completely <em>free<\/em> (it was inexpensive at the time the article was written).<\/p>\n<p>That being said, if you must use a shared development database, you can try to work around the limitations. You may need to take special configuration steps, depending on the tool. For example, if you are using SQL Source Control, you may use a \u201c<a href=\"https:\/\/documentation.red-gate.com\/soc6\/linking-to-source-control\/other-source-control-systems\/link-to-a-custom-setup?_ga=2.220219992.1745729603.1603973364-666432276.1591170473&amp;_gac=1.255928057.1600335456.CjwKCAjwkoz7BRBPEiwAeKw3q3J1ZCsRLR9RHshzDn3y8gHj6ur9kssQVzKK6lSXckQ_I6MhL2vbrBoC3-MQAvD_BwE\">custom<\/a>\u201d connection to access a shared database via Git. You may be able to use object locking in your database tool to mitigate the risks of overwriting each other\u2019s work, but you will still see changes in the shared development databases made by other people appear as suggested changes which you could import to version control, which <a href=\"https:\/\/productsupport.red-gate.com\/hc\/en-us\/articles\/360007957193-Using-Shared-Mode-with-Git\">can be very confusing<\/a>.<\/p>\n<p>Essentially, even if you are sharing a single branch, using a distributed version control system such as Git \u2013 where developers each maintain their <em>own<\/em> local copy of the repo and do not all push and pull to the repo simultaneously \u2013 makes using a shared database environment for development awkward.<\/p>\n<p>Whether or not you are using shared or dedicated databases, it is worth your while to get into the practice of using individual feature branches and a Pull Request workflow because of the following benefits.<\/p>\n<h2>Building good practices<\/h2>\n<p>There are five major things which I really like about this workflow:<\/p>\n<p><strong>1. Team members may share changes safely and easily <\/strong>&#8211; Imagine that Amy and Beth do the same changes as above at the same times, but they are both working in the main branch. If either Amy or Beth attempts to push new commits to the main branch and it has been updated since they last pushed, they will get an error that the origin has changed and they cannot push.<\/p>\n<p>What if Amy or Beth is working on an experimental change that they\u2019d like to get feedback on from a team member, without having to integrate other changes? There isn\u2019t a good way to do that when they are sharing the branch.<\/p>\n<p><strong>2. You may push changes upstream regularly without fear <\/strong>\u2013 It\u2019s convenient to work in a distributed VCS like Git because you can work in a disconnected fashion when you need to. If you\u2019re using a hosted Git repo like Azure DevOps Services or GitHub and your internet connection fails, no problem! You can still commit locally. However, I think it\u2019s also a good practice to back up your changes by regularly pushing them upstream to the repo. If you have a hardware failure locally or accidentally delete the wrong folder, no worries, you haven\u2019t lost work. Working in a private topic branch means you can push your branch up to the upstream repo anytime without worry about needing to handle a conflict.<\/p>\n<p><strong>3. It makes merging purposeful and frequent <\/strong>\u2013 In the scenario where Amy and Beth are both working simultaneously on a shared branch, if one of them pushes a commit, the other will need to merge the changes the next time they pull. This may be done automatically by a Git client if there is no conflict, but if they are working on any of the same files, when pulling they will need to pause to go resolve the conflict. Because this occurs only sometimes on a pull, this feels like a distraction and a break in flow.<\/p>\n<p>To contrast, if Amy and Beth have the habit of working in their own feature branches, they can develop a habit of periodically comparing their branch with mainline branches at the origin, and deciding when they want to merge in changes from those branches. This tends to make merges happen at a point when the developer is ready to consider the merge\u2014not when they might be thinking about solving another problem.<\/p>\n<p><strong>3. It allows frequent commits <\/strong>\u2013 Many times when people begin working in a shared branch in Git, it isn\u2019t just <em>any<\/em> branch \u2013 it\u2019s a mainline branch. In other words, it\u2019s a branch that regularly (and perhaps automatically) deploys code to an environment. Doing your early development work in a shared mainline branch like this has some bad effects: it means you are either less likely to experiment, or you are less likely to commit your changes regularly. After all, what if you commit something that is an experiment which you don\u2019t want to get deployed? Well, you\u2019re going to have to undo those commits \u2013 that\u2019s not hard, but do you want a commit history full of doing things and then undoing them? Getting into the habit of working in feature branches gives you much more freedom: you can commit and undo commits knowing that at the time you get to a Pull Request, you\u2019ll have some options on squashing your commit history easily when you merge in. Or, if you prefer not to squash commit history, you can always create a temporary feature branch from your existing feature branch to play around with some changes before you decide what you want to do.<\/p>\n<p><strong>5. It encourages early change review and communication <\/strong>\u2013 So far, I\u2019ve mainly talked about using Pull Requests as the way in which you merge changes from one branch into another. This is only a small bit of the value PRs give you. PRs often function as a major point of communication and review. Most hosted Git options even allow you to do things like automatically add reviewers and require a specific number of reviewers for a PR to be approved. When a PR is opened, you may also have it automatically run a build and test the code, potentially even deploying it to an environment for the reviewers to examine. In short, PR workflows promote communication and review early in code development. The workflow can be a strong foundation for ensuring you have quality code.<\/p>\n<p><strong>Q: What if I forget to use a feature branch?<\/strong><\/p>\n<p>If you want everyone to use a PR workflow, you may choose to protect some branches. Many hosted Git providers allow ways to do this: you can <a href=\"https:\/\/docs.github.com\/en\/free-pro-team@latest\/github\/administering-a-repository\/configuring-protected-branches\">configure protected branches in GitHub<\/a>, <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/devops\/repos\/git\/branch-policies?view=azure-devops\">create a branch policy in Azure DevOps,<\/a> or <a href=\"https:\/\/confluence.atlassian.com\/bitbucketserver\/using-branch-permissions-776639807.html\">set Branch Permissions in BitBucket<\/a>, for example. The protections or policies are generally enforced upstream at the origin. If you commit changes locally to a protected branch and attempt to push them, this will result in an error that you\u2019re not allowed to change the upstream branch directly. In this case, you can usually create another branch locally off your updated main branch and proceed from there. If you have some work in progress that you aren\u2019t ready to commit, <a href=\"https:\/\/git-scm.com\/book\/sv\/v2\/Git-Tools-Stashing-and-Cleaning\">you may want to stash it<\/a>.<\/p>\n<h2>A detailed video example \u2013 \u201cSQL Source Control and VSCode: Handling Git Conflicts\u201d<\/h2>\n<p>In this <a href=\"https:\/\/youtu.be\/mNXipSFbV0s\">video<\/a>, I\u2019m using a dedicated development database model with the following setup:<\/p>\n<ul>\n<li><a href=\"https:\/\/dev.azure.com\/\">Azure DevOps Services<\/a> Organization and Project \u2013 this hosts the upstream Git Repo.\n<ul>\n<li>The upstream repo is used to push and pull changes for Git clients doing the work. The upstream Git Repo is also where Pull Requests are created, reviewed, approved, and completed.<\/li>\n<li>I have cloned two copies of the same Git repo to my local workstation so that I can simulate working as two people, each in their own local repo.<\/li>\n<\/ul>\n<\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/products\/sql-development\/sql-source-control\">SQL Source Control<\/a> \u2013 this compares the SQL Server database to the code in the Git Repo.\n<ul>\n<li>It identifies when there are changes in the development database to commit <em>to<\/em> the repo, automatically scripts changes to commit to the repo, and helps keep the development database in sync when new changes come <em>from<\/em> the Git repo.<\/li>\n<li>I\u2019ve already created a SQL Source Control project and committed it to the repo. Both of my local copies of the repo begin with having pulled down copies of the project.<\/li>\n<\/ul>\n<\/li>\n<li>VSCode and Azure Data Studio \u2013 These free tools from Microsoft share the same free Git client. In this example I use these tools to manage my merge conflicts.\n<ul>\n<li>I\u2019m using VSCode to represent one user and Azure Data Studio to represent the other, simply because I can set different color schemes in them and it makes it easier for me to track.<\/li>\n<li>I have <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=eamodio.gitlens\">the free GitLens extension<\/a> installed in both VSCode and Azure Data Studio. This extension makes it easy to see details of commit history and has many more useful options. This is totally optional, simply nice to have in my experience.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>A list of chapters is below if you\u2019d like an overview, or if you\u2019d like to jump to specific sections.<\/p>\n<p>Chapters in the video:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=0s\">00:00<\/a> Overview of the demo setup<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=127s\">02:07<\/a> Demo begins of a merge conflict when working in the same branch as your teammates<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=197s\">03:17<\/a> Why conflicts occur as interrupts if we work in the same branch in Git<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=275s\">04:35<\/a> Interpreting Git conflict messages in SQL Source Control<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=358s\">05:58<\/a> Resolving a merge conflict within your current branch<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=517s\">08:37<\/a> Why working in private feature branches is a common practice for Git users<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=642s\">10:42<\/a> Traveling back in time with the GitLens extension<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=727s\">12:07<\/a> Resetting SQL Source Control after resetting in Git<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=870s\">14:30<\/a> Demo begins of working in a feature branch in SQL Source Control, and proactively merging from main when we&#8217;re ready<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=917s\">15:17<\/a> Checking out a new branch in VSCode<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=1098s\">18:18<\/a> Merge changes from the upstream main branch into our feature branch. I have enabled VSCode to regularly fetch changes, so I haven&#8217;t manually &#8216;fetched&#8217;.<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=1238s\">20:38<\/a> Resolving the conflict in VSCode<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=1420s\">23:40<\/a> Staging and committing to complete the merge<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=1505s\">25:05<\/a> Applying changes we made in VSCode to our dev database in SQL Source Control<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=1566s\">26:06<\/a> Pushing our changes to the central Git repo and creating a Pull Request<\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=mNXipSFbV0s&amp;t=1740s\">29:00<\/a> Approving and completing the Pull Request<\/li>\n<\/ul>\n<h2>Branching and merging in Git is not as hard as it may seem at first glance!<\/h2>\n<p>If you are new to Git, this can seem daunting to learn.<\/p>\n<p>While Git can be quite complex, I have found that hands-on experience with Git and practicing in a test project got me a <em>long<\/em> way, and it happened faster than I expected. The branching workflows described in this article have also made my work in Git flow easier, which has made it less frustrating and more fun.<\/p>\n<p>I hope this pattern proves useful to your team as well.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Feature branching and pull requests are two important concepts when using Git. In this article, Kendra Little explains these patterns and even provides a video to demonstrate.&hellip;<\/p>\n","protected":false},"author":321187,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143516,53],"tags":[124952],"coauthors":[61458],"class_list":["post-89209","post","type-post","status-publish","format-standard","hentry","category-database-devops","category-featured","tag-redgate-deploy"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/89209","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/321187"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=89209"}],"version-history":[{"count":3,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/89209\/revisions"}],"predecessor-version":[{"id":89239,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/89209\/revisions\/89239"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=89209"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=89209"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=89209"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=89209"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}