# Choosing the right git branching strategy .footnote[By [Rejah Rehim](https://rejahrehim.com)] --- name: Title class: middle, center
# Choosing the right
branching strategy --- name: About me class: middle, center # About me ## Founder Appfabs and Beagle Security
[https://beaglesecurity.com](https://beaglesecurity.com)
--- name: What is Git class: middle, center # What is Git? -- Open-source code management tool -- Created by Linus Torvalds when he was building the Linux kernel. -- Git is DSCS (Distributed Source Control System) ??? This means that even if you're using a centralized work-flow, every user essentially has a full backup of the main server. Each of these copies could be pushed up to replace the main server in the event of a crash or corruption. In effect, there is no single point of failure with Git unless there is only a single copy of the repository. -- Git allows you to work on your code with the peace of mind that
everything you do is reversible
. --- name: Branching and Merging class: middle, center # Branching and Merging ### Git allows and encourages you to have multiple local branches that can be entirely independent of each other. -
Frictionless Context Switching
- Create a branch to try out an idea, commit a few times, switch back to where you branched from. -
Feature Based Work-flow
- Create new branches for each new feature you're working on so you can seamlessly switch back and forth between them, then delete each branch when that feature gets merged into your main line. -
Disposable Experimentation
- Create a branch to experiment in, realize it's not going to work, and just delete it - abandoning the work --- name: Distributed class: middle, center # Distributed
### This means that even if you're using a centralized work-flow, every user essentially has a full backup of the main server. Each of these copies could be pushed up to replace the main server in the event of a crash or corruption. In effect, there is no single point of failure with Git unless there is only a single copy of the repository. --- name: Staging class: middle, center # Staging Area
### Unlike the other systems, Git has something called the "staging area" or "index". This is an intermediate area where commits can be formatted and reviewed before completing the commit. ### It's possible to quickly stage some of your files and commit them without committing all of the other modified files in your working directory ??? Unlike the other systems, Git has something called the "staging area" or "index". This is an intermediate area where commits can be formatted and reviewed before completing the commit. It's possible to quickly stage some of your files and commit them without committing all of the other modified files in your working directory --- name: standard class: middle, center # Install Git -- ## Installing on Linux -- If you’re on Fedora (or any closely-related RPM-based distribution, such as RHEL or CentOS), you can use dnf: ``` $ sudo dnf install git-all ``` -- If you’re on a Debian-based distribution, such as Ubuntu, try apt: ``` $ sudo apt install git-all ``` --- name: standard class: middle, center ## Installing on Mac -- The easiest method is, install the Xcode Command Line Tools. -- More up to date version, download at the Git website. http://git-scm.com/download/mac. --- name: standard class: middle, center ## Installing on Windows -- official build is available for download on the Git website. Just go to http://git-scm.com/download/win and the download --- name: setup class: middle, center # Setup
--- name: setup class: middle, center # Setup Name and Email Run the following commands so that git knows your name and your email ``` $ git config --global user.name "Your Name" $ git config --global user.email "you@appfabs.com" ``` --- name: setup class: middle, center # Setup Line Ending Preferences -- Unix/Mac users: ``` $ git config --global core.autocrlf input $ git config --global core.safecrlf true ``` -- Windows users: ``` $ git config --global core.autocrlf true $ git config --global core.safecrlf true ``` --- name: setup class: middle, center # SetUp Editor & Diff tool -- Setup default editor ``` $ git config --global core.editor emacs ``` -- Another useful option you may want to configure is the default diff tool to use to resolve merge conflicts. ``` $ git config --global merge.tool vimdiff ``` --- name: setup class: middle, center # Create / Clone a project Create the Repository ``` $ git init Initialized empty Git repository in /Users/rejah/working/directory/.git/ ``` -- Clone a Repository ``` $ git clone git@letzgame.com:testing.git Cloning into 'testing'... remote: Counting objects: 21, done. remote: Compressing objects: 100% (17/17), done. remote: Total 21 (delta 2), reused 0 (delta 0) Receiving objects: 100% (21/21), 2.50 MiB, done. Resolving deltas: 100% (2/2), done ``` --- name: add-program class: middle, center # Add the program to the repository ``` $ git add hello.php $ git commit -m "Add hellp.php to the repo" [master (root-commit) 9416416] First Commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 hello.php ``` --- name: add-program class: middle, center # Check the status of the repository git status to check the current status of the repo. ``` $ git status # On branch master nothing to commit (working directory clean) ``` ``` $ git status # On branch master # Changes not staged for commit: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: hello.php # no changes added to commit (use "git add" and/or "git commit -a") ``` --- name: add-program class: middle, center # Staging changes ``` $ git add hello.php $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # modified: hello.php # ``` The change to the `hello.php` file has been staged. This means that git now knows about the change, but the change hasn’t been permanently recorded in the repository yet. The next commit operation will include the staged changes. ??? If you decide you don’t want to commit that change after all, the status command reminds you that the git reset command can be used to unstage that change. --- name: add-program class: middle, center # Staging and Committing Suppose you edited three files (`a.php`, `b.php`, and `c.php`). Now you want to commit all the changes, but you want the changes in a.php and b.php to be a single commit, while the changes to c.php are not logically related to the first two files and should be a separate commit. ``` git add a.php git add b.php git commit -m "Add Changes for a and b" git add c.php git commit -m "Add Unrelated change to c" ``` By separating staging and committing, you have the ability to easily fine tune what goes into each commit. --- name: add-program class: middle, center # Committing Changes ``` git commit ``` You should see the following in your default editor: ``` | # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # modified: hello.php # ``` On the first line, enter the comment: “Test Commit”. Save the file and exit the editor. Provide Commit message ``` git commit -m "Test Commit" ``` --- name: add-program class: middle, center # Better commit message -- Separate subject from body with a blank line -- Limit the subject line to 50 characters --- class: middle, center # Better commit message Capitalize the subject line For example:
Accelerate to 88 miles per hour
Instead of:
accelerate to 88 miles per hour
--- class: middle, center # Better commit message Do not end the subject line with a period Example:
Open the pod bay doors
Instead of:
Open the pod bay doors.
--- class: middle, center # Better commit message Use the imperative mood in the subject line That is as if you were commanding someone. Start the line with "Fix", "Add", "Change" instead of "Fixed", "Added", "Changed". examples: ``` refactor subsystem X for readability ``` Git commit subject line should always be able to complete the following sentence: For example: If applied, this commit will
refactor subsystem X for readability
If applied, this commit will
update getting started documentation
If applied, this commit will
merge pull request #123 from user/branch
Will not work in non-imperative forms: If applied, this commit will
fixed bug with Y
If applied, this commit will
changing behavior of X
--- class: middle, center # Better commit message Wrap the body at 72 characters -- Use the body to explain what and why vs. how This commit from Bitcoin Core is a great example: ``` commit eb0b56b19017ab5c16c745e6da39c53126924ed6 Author: Pieter Wuille
Date: Fri Aug 1 22:57:55 2014 +0200 Simplify serialize.h's exception handling Remove the 'state' and 'exceptmask' from serialize.h's stream implementations, as well as related methods. As exceptmask always included 'failbit', and setstate was always called with bits = failbit, all it did was immediately raise an exception. Get rid of those variables, and replace the setstate with direct exception throwing (which also removes some dead code). As a result, good() is never reached after a failure (there are only 2 calls, one of which is in tests), and can just be replaced by !eof(). fail(), clear(n) and exceptions() are just never called. Delete them. ``` ??? If it seems difficult to summarize what your commit does, it may be because it includes several logical changes or bug fixes, and are better split up into several commits using git add -p. --- name: add-program class: middle, center # History Getting a listing of what changes have been made is the function of the git log command. ``` $ git log commit 1f7ec5eaa8f37c2770dae3b984c55a1531fcc9e7 Author: Rejah Date: Sat Apr 13 15:20:42 2013 -0400 Add a comment commit 582495ae59ca91bca156a3372a72f88f6261698b Author: Rejah Date: Sat Apr 13 15:20:42 2013 -0400 Add a default value ``` --- class: middle, center # One Line Histories ``` $ git log --pretty=oneline 1f7ec5eaa8f37c2770dae3b984c55a1531fcc9e7 Add a comment 582495ae59ca91bca156a3372a72f88f6261698b Add a default value 323e28d99a07d404c04f27eb6e415d4b8ab1d615 Use ARGV for arg parsing 94164160adf8faa3119b409fcfcd13d0a0eb8020 inital Commit ``` -- # Controlling Which Entries are Displayed You have a great deal of control over exactly what the log command displays. ``` git log --pretty=oneline --max-count=2 git log --pretty=oneline --since='5 minutes ago' git log --pretty=oneline --until='5 minutes ago' git log --pretty=oneline --author= git log --pretty=oneline --all ``` --- class: middle, center # Getting Old Versions ``` $ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short * 1f7ec5e 2013-09-13 | Add a comment (HEAD, master) [Rejah] * 582495a 2013-09-13 | Add a default value [Rejah] * 323e28d 2013-09-13 | Use ARGV [Rejah] * 9416416 2013-09-13 | Inital Commit [Rejah] ``` ``` $ git checkout 9416416 Note: checking out '9416416'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b new_branch_name HEAD is now at 9416416... Inital Commit ``` --- class: middle, center # Return the latest version in the master branch ``` $ git checkout master Previous HEAD position was 9416416... Inital Commit Switched to branch 'master' ``` --- name: add-program class: middle, center # Tagging
--- name: tagging class: middle, center # Tagging versions ``` $ git tag v1 ``` Now you can refer to the current version of the program as v1. Checking Out by Tag Name ``` $ git checkout v1 Previous HEAD position was 582495a... Add a default value HEAD is now at 1f7ec5e... Add a comment $ git checkout v1-beta Previous HEAD position was 1f7ec5e... Add a comment HEAD is now at 582495a... Add a default value ``` --- name: tag-command class: middle, center # Viewing Tags using the tag command ``` $ git tag v1 v1-beta ``` Viewing Tags in the Logs ``` $ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short master --all * 1f7ec5e 2013-04-13 | Add a comment (v1, master) [Jim Weirich] * 582495a 2013-04-13 | Add a default value (HEAD, v1-beta) [Jim Weirich] * 323e28d 2013-04-13 | Using ARGV [Jim Weirich] * 9416416 2013-04-13 | First Commit [Jim Weirich] ``` --- name: tag-command class: middle, center # Removing tag ``` $ git tag -d oops Deleted tag 'oops' (was a10293f) ``` --- name: tag-command class: middle, center # UNDOING
--- name: tag-command class: middle, center # Local Changes (before staging) Sometimes you have modified a file in your local working directory and you wish to just revert to what has already been committed. The checkout command will handle that. ``` git checkout hello.php git status vim hello.php ``` --- name: tag-command class: middle, center # Staged Changes (before committing) ``` $ git reset HEAD hello.php Unstaged changes after reset: M hello.php ``` The reset command resets the staging area to be whatever is in HEAD. This clears the staging area of the change we just staged. The reset command (by default) doesn’t change the working directory. So the working directory still has the unwanted code in it. --- name: tag-command class: middle, center # Undoing Committed Changes Change that you have already committed was not correct and you wish to undo that commit. ``` $ git revert HEAD --no-edit [master a10293f] Revert "Oops, we didn't want this commit" 1 files changed, 1 insertions(+), 1 deletions(-) ``` A revert operation will take the specified commit, inverse the changes from that commit, and create a new "revert commit". ``` $ git reset --hard v1 HEAD is now at 1f7ec5e Added a comment $ git hist * 1f7ec5e 2013-04-13 | Add a comment (HEAD, master) [Rejah] * 582495a 2013-04-13 | Add a default value (v1-beta) [Rejah] ``` ??? Since we were undoing the very last commit we made, we were able to use HEAD as the argument . We can revert any arbitrary commit earlier in history by simply specifying its hash value. Note: The --no-edit in the output can be ignored. used to generate the output without opening the editor. --- name: restting-vs-reverting class: middle, center # Resetting vs Reverting
--- class: middle, center # Git Reset vs Revert vs Checkout reference | Command | Scope | Common use cases | |---------|--------------------|--------------------| | git reset | Commit-level | Discard commits in a private branch or throw away uncommited changes | | git reset | File-level | Unstage a file | | git checkout | Commit-level | Switch between branches or inspect old snapshots | | git checkout | File-level | Discard changes in the working directory | | git revert | Commit-level | Undo commits in a public branch | | git revert | File-level | (N/A) | --- class: middle, center # Amending Commits After you make the commit, you realize that any good author comment should have an email included. Update the hello program to include an email. ``` git add hello.php git commit --amend -m "Add an author/email comment" ``` --- name: restting-vs-reverting class: middle, center # Branches
--- name: restting-vs-reverting class: middle, center # Create a Branch ``` $ git checkout -b greet $ git status ``` git checkout -b
is a shortcut for git branch
followed by a git checkout
. --- name: restting-vs-reverting class: middle, center # Navigating Branches ``` $ git checkout master Switched to branch 'master' ``` # Merge the branches ``` $ git merge master Merge made by recursive. README | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 README ``` --- name: conflicts class: middle, center # Resolving Conflicts
--- class: middle, center ``` $ git checkout newbranch Switched to branch 'newbranch' $ git merge master Auto-merging lib/hello.php CONFLICT (content): Merge conflict in lib/hello.php Automatic merge failed; fix conflicts and then commit the result. ``` If you open lib/hello.php, you will see: ``` <<<<<<< HEAD:mergetest This is my third line ======= This is a fourth line I am adding >>>>>>> 4e2b407f501b68f8588aa645acafffa0224b9b78:mergetest ```
<<<<<<<
: Indicates the start of the lines that had a merge conflict. The first set of lines are the lines from the file that you were trying to merge the changes into.
=======
: Indicates the break point used for comparison. Breaks up changes that user has committed (above) to changes coming from merge (below) to visually see the differences.
>>>>>>>
: Indicates the end of the lines that had a merge conflict. --- name: conflicts class: middle, center # How do I resolve a merge conflict in a file? You resolve a conflict by editing the file to manually merge the parts of the file that git had trouble merging. This may mean discarding either your changes or someone else's or doing a mix of the two. You will also need to delete the
<<<<<<<
,
=======
, and
>>>>>>>
in the file. --- name: conflicts class: middle, center # What do I do after I've resolved conflicts in all affected files? Commit the Conflict Resolution git add the file(s) ``` $ git add -A ``` git commit and git push (Push only for branches tracked.) ``` $git commit -m "Resolve Conflict in merge A and B" $git push ``` --- class: middle, center # Merging vs. Rebasing
Both of these commands are designed to integrate changes from one branch into another branch, they just do it in very different ways.
--- class: middle, center ## Consider what happens when you start working on a new feature in a dedicated branch, then another team member updates the master branch with new commits.
--- class: middle, center ## The Merge Option ``` git checkout feature git merge master ``` ``` git merge feature master ``` --- class: middle, center
This creates a new “merge commit” in the feature branch that ties together the histories of both branches
Merging is nice because it’s a non-destructive operation
If master is very active, this can pollute your feature branch’s history quite a bit. --- class: middle, center ## The Rebase Option ``` git checkout feature git rebase master ``` --- class: middle, center
The major benefit of rebasing is that you get a much cleaner project history. First, it
eliminates the unnecessary merge commits required by git merge
. Second, as you can see in the above diagram, rebasing also results in a
perfectly linear project history
--- class: middle, center # The Golden Rule of Rebasing Once you understand what rebasing is, the most important thing to learn is when not to do it. -- ## The golden rule of `git rebase` is to
never use it on public branches
. --- class: middle, center
The rebase moves all of the commits in master onto the tip of feature. The problem is that this only happened in your repository. All of the other developers are still working with the original master. Since rebasing results in brand new commits, Git will think that your master branch’s history has diverged from everybody else’s. --- class: middle, center # Using an external merge tool meld
--- name: restting-vs-reverting class: middle, center # What is Origin? ``` $ git remote origin ``` We see that the cloned repository knows about a remote repository ``` $ git remote show origin * remote origin Fetch URL: git@letzgame.com:testing.git Push URL: git@letzgame.com:testing.git HEAD branch: master Remote branch: master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date) ``` --- name: restting-vs-reverting class: middle, center # What is Origin? Remote repositories typically live on a separate machine, possibly a centralized server. There is nothing particularly special about the name “origin”, however the convention is to use the name “origin” for the primary centralized repository (if there is one). --- name: restting-vs-reverting class: middle, center # Remote Branches ``` $ git branch * master ``` That’s it, only the master branch is listed. The git branch command only lists the local branches by default. ``` $ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/greet remotes/origin/master ``` Git has all the commits from the original repository, but branches in the remote repository are not treated as local branches here. If we want our own , we need to create it ourselves. --- name: restting-vs-reverting class: middle, center # Working With Remote
--- name: restting-vs-reverting class: middle, center # Adding a Remote Repository Let’s add the testing.git repo to our original repo. ``` git remote add git@letzgame.com:testing.git ``` Add a local branch that tracks a remote branch ``` $ git branch --track newbranch origin/greet Branch newbranch set up to track remote branch newbranch from origin. $ git branch -a newbranch * master remotes/origin/HEAD -> origin/master remotes/origin/newbranch remotes/origin/master ``` We can now see the greet branch in the branch list and in the log. --- name: restting-vs-reverting class: middle, center # Fetching Changes ``` $ git fetch From /Users/jim/working/git/git_immersion/auto/hello 2fae0b2..2e4c559 master -> origin/master ``` The “git fetch” command will fetch new commits from the remote repository, but it will not merge these commits into the local branches. # Merging Pulled Changes ``` $ git merge origin/master Updating 2fae0b2..2e4c559 Fast-forward README | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) ``` --- name: restting-vs-reverting class: middle, center # Pushing a Change ``` $ git push origin master To git@letzgame.com:testing.git 2e4c559..3923dd5 master -> master ``` --- name: restting-vs-reverting class: middle, center # Pulling Change We’re not going to go through the process of creating another change and pulling it again, but we do want you to know that doing: ``` $ git pull origin master ``` is indeed equivalent to the two steps: ``` $ git fetch $ git merge origin/master ``` origin is the name of the repository receiving the changes we are pushing. (Remember, we added it as a remote) --- name: restting-vs-reverting class: middle, center # Stash When you’ve been working on part of your project, things are in a messy state and you want to switch branches for a bit to work on something else. -- Put in stash: ``` git stash save "Message" ``` -- Show stash: ``` git stash list ``` -- Show stash stats: ``` git stash show stash@{0} ``` -- Show stash changes: ``` git stash show -p stash@{0} ``` --- name: restting-vs-reverting class: middle, center Use custom stash item and drop it: ``` git stash pop stash@{0} ``` -- Use custom stash item and do not drop it: ``` git stash apply stash@{0} ``` -- Delete custom stash item: ``` git stash drop stash@{0} ``` -- Delete complete stash: ```` git stash clear ``` --- name: restting-vs-reverting class: middle, center # Gitignore & Gitkeep -- There are files you don't want Git to track it Create a file in your repository named `.gitignore` -- If you already have a file checked in, and you want to ignore it ``` git rm --cached FILENAME ``` -- Generate simple gitignore from
https://www.gitignore.io/
-- Track empty dir by putting `.gitkeep` file inside it ??? Ignored files are usually build artifacts and machine generated files that can be derived from your repository source or should otherwise not be committed. Some common examples are: dependency caches, such as the contents of /node_modules or /packages compiled code, such as .o, .pyc, and .class files build output directories, such as /bin, /out, or /target files generated at runtime, such as .log, .lock, or .tmp hidden system files, such as .DS_Store or Thumbs.db personal IDE config files, such as .idea/workspace.xml --- name: restting-vs-reverting class: middle, center # Compare -- Compare modified files: ``` git diff ``` -- Compare modified files and highlight changes only: ``` git diff --color-words index.html ``` -- Compare modified files within the staging area: ``` git diff --stage ``` -- Compare modified files between two commits: ``` git diff 6eb715d 537a09f ``` --- name: restting-vs-reverting class: middle, center # Workflow
--- class: middle, center # Why Workflows? -- Git workflows encourage users to leverage Git effectively and consistently. -- Git offers a lot of flexibility in how users manage changes. -- There is no standardized process on how to interact with Git. -- When working with a team on a Git managed project, it’s important to make sure the team is all in agreement on how the flow of changes will be applied. -- To ensure the team is on the same page, an agreed upon Git workflow should be developed or selected. --- name: restting-vs-reverting class: middle, center # Centralized Workflow
The centralized workflow. One central hub, or repository, can accept code, and everyone synchronizes their work to it --- class: middle, center
Developers start by cloning the central repository. In their own local copies of the project, they edit files and commit changes To publish changes to the official project, developers `push` their local `master` branch to the central repository. --- class: middle, center # Example ## John works on his feature
--- class: middle, center # Example ## Mary works on her feature
--- class: middle, center # Example ## John publishes his feature
``` git push origin master ``` --- class: middle, center # Example ## Mary tries to publish her feature
``` git push origin master ``` --- class: middle, center # Example But, since her local history has diverged from the central repository, Git will refuse the request ``` error: failed to push some refs to '/path/to/repo.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Merge the remote changes (e.g. 'git pull') hint: before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. ``` How to resolve
[conflicts?](https://rejahrehim.com/blog/git/workshop/presentation/slide/2019/12/08/choosing-the-right-git-branching-strategy.html#63)
--- class: middle, center # Example ## Mary rebases / merge on top of John’s commit(s)
``` git pull origin master ``` ``` git pull --rebase origin master ``` What is
[rebase](https://rejahrehim.com/blog/git/workshop/presentation/slide/2019/12/08/choosing-the-right-git-branching-strategy.html#67)
--- class: middle, center # Example ## Mary resolves a merge conflict
``` git pull origin master ``` ``` git pull --rebase origin master ``` --- class: middle, center # Example ## Mary successfully publishes her feature
``` git push origin master ``` --- name: restting-vs-reverting class: middle, center # Integration-Manager Workflow
--- class: middle, center
A contributor clones from the blessed repository and makes changes --- class: middle, center
Contributor push to their own public repo --- class: middle, center
The contributor sends the maintainer an email / pull request asking them to pull changes. The maintainer adds the contributor’s repository as a remote and merges locally. --- class: middle, center
The maintainer pushes merged changes to the main repository --- name: restting-vs-reverting class: middle, center # Dictator and Lieutenants Workflow
-- Regular developers work on their topic branch and rebase their work on top of master. The master branch is that of the reference repository to which the dictator pushes. -- Lieutenants merge the developers' topic branches into their master branch. -- The dictator merges the lieutenants' master branches into the dictator’s master branch. -- Finally, the dictator pushes that master branch to the reference repository so the other developers can rebase on it. --- name: restting-vs-reverting class: middle, center # Branching Workflow
--- class: middle, center # Feature Branch Workflow The core idea behind the Feature Branch Workflow is that all feature development should take place in a dedicated branch instead of the master branch. This encapsulation makes it easy for multiple developers to work on a particular feature without disturbing the main codebase. `master` branch will never contain broken code, which is a huge advantage for continuous integration environments. --- class: middle, center # How it works ## Start with the master branch ``` git checkout master git fetch origin git reset --hard origin/master ``` This switches the repo to the master branch, pulls the latest commits and resets the repo's local copy of master to match the latest version. --- class: middle, center # How it works ## Create a new-branch ``` git checkout -b new-feature ``` Use a separate branch for each feature or issue you work on. After creating a branch, check it out locally so that any changes you make will be on that branch. --- class: middle, center # How it works ## Update, add, commit ``` git status git add
git commit ``` On this branch, edit, stage, and commit changes in the usual fashion, building up the feature with as many commits as necessary. --- class: middle, center # How it works ## Push feature branch to remote ``` git push -u origin new-feature ``` This command pushes new-feature to the central repository (origin), and the -u flag adds it as a remote tracking branch. --- class: middle, center # How it works ## Pull request / Merge request
Code review is a major benefit of pull requests, but they’re actually designed to be a generic way to talk about code. --- class: middle, center # How it works ## Merge your pull request Before you merge, you may have to resolve merge conflicts if others have made changes to the repo. When your pull request is approved and conflict-free, you can add your code to the master branch. Merge from the pull request in Bitbucket. --- name: restting-vs-reverting class: middle, center # Git-Flow Workflow
--- name: restting-vs-reverting class: middle, center # Decentralized but centralized
--- name: restting-vs-reverting class: middle, center # The main branches
The central repo holds two main branches with an infinite lifetime: master develop Instead of a single master branch, this workflow uses two branches to record the history of the project. --- class: middle, center # Master branch This is the main branch of the repository from which we make releases to the store or to the release server. -- Access is restricted. -- Changes can be submitted only through Pull Requests. No direct commits are allowed. -- Should always have the latest release version on store/production release server. -- Should never have unreleased code(commits made but not yet released). --- class: middle, center # Develop branch This is the main 'development' branch of the repository. This branch is based on the 'master' branch on creation. It tracks the current development. -- Access is restricted. -- No direct commits are allowed under normal circumstances. If a situation arises, direct commits can be made with the approval of the entire team. -- Changes can be submitted through Pull Requests. -- Pull requests should be peer reviewed and approved by all or some of the team members. -- Should always have the latest alpha/beta release version. It shouldn't have unreleased code(Commits made but not released yet). -- Base branch for user/feature branches. --- name: restting-vs-reverting class: middle, center # Supporting branches The different types of branches are: Feature branches Release branches Hotfix branches --- name: restting-vs-reverting class: middle, center # Feature branches Each new feature should reside in its own branch, which can be pushed to the central repository for backup/collaboration.
``` git checkout develop git checkout -b feature-branch ``` --- name: restting-vs-reverting class: middle, center # Release branches
``` git checkout develop git checkout -b release/0.1.0 ``` Once develop has acquired enough features for a release (or a predetermined release date is approaching), you fork a release branch off of develop. Using a dedicated branch to prepare releases makes it possible for one team to polish the current release while another team continues working on features for the next release. --- name: restting-vs-reverting class: middle, center # Hotfix branches
Maintenance or “hotfix” branches are used to quickly patch production releases. --- class: middle, center # Example ``` git checkout master git checkout -b develop git checkout -b feature_branch # work happens on feature branch git checkout develop git merge feature_branch git checkout master git merge develop git branch -d feature_branch ``` --- name: restting-vs-reverting class: middle, center # GitHub flow
--- class: middle, center # GitHub flow Create a branch from the repository `master` branch. -- Create, edit, rename, move, or delete files. -- Send a pull request from your branch with your proposed changes to kick off a discussion. -- Make changes on your branch as needed. Your pull request will update automatically. -- Merge the pull request once the branch is ready to be merged. -- Tidy up your branches using the delete button in the pull request or on the branches page. --- name: restting-vs-reverting class: middle, center # Release Flow – Microsoft’s Azure DevOps
-- In this strategy, the teams do not continuously deploy master to production. -- Instead, they release the master branch every sprint by creating a branch for each release. -- When the teams need to bring hotfixes into production, they cherry-pick those changes from master into the release branch. --- name: restting-vs-reverting class: middle, center # Forking Workflow -- The Forking Workflow is fundamentally different than other popular Git workflows. -- Instead of using a single server-side repository to act as the “central” codebase,
it gives every developer their own server-side repository
. -- The main advantage of the Forking Workflow is that contributions can be integrated without the need for everybody to push to a single central repository. --- class: middle, center # Forking vs cloning Forked repositories are generally "server-side clones" and usually managed and hosted by a 3rd party Git service like Bitbucket. There is no unique Git command to create forked repositories. --- class: middle, center # Adding a remote ``` git remote add upstream https://bitbucket.org/maintainer/repo ``` --- class: middle, center # How it works A developer `forks` an `official` server-side repository. This creates their own server-side copy. -- The new server-side copy is cloned to their local system. -- A Git remote path for the `official` repository is added to the local clone. -- A new local feature branch is created. -- The developer makes changes on the new branch. -- New commits are created for the changes. -- The branch gets pushed to the developer's own server-side copy. -- The developer opens a pull request from the new branch to the 'official' repository. -- The pull request gets approved for merge and is merged into the original server-side repository --- class: middle, center # So which one should I use? -- ## It depends -- What type of product are we releasing? -- Will we be required to maintain multiple releases of this product in production? -- Do we need continuous deployment? -- Is our team better suited and experienced at using Release branches? -- If team was more focused on continuous deployment and not ready to use a Release branch with cherry picking from Master to Release - we can negate Release Flow strategy from consideration --- class: middle, center # Which one do I use? -- I use GitHub Flow for most of my projects. --- name: restting-vs-reverting class: middle, center # Thanks