git and git-flow, part 2

Introduction

Back in August 2019, I wrote git and git-flow, a guide. I intended it to be used internally by GumGum to familiarize new hires with the workflow we use.

  • Working with Epics and Sub-Tasks
  • Fixing bugs in production
  • Avoid rebasing conflicts with --onto
  • Stashing work in progress
  • Many helpful commands

About our project

Our project is incredibly trivial but helps showcase the topics covered by this guide. It is an HTML file that has slowly grown by working on different tickets.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Learning Git Flow</title>
</head>
<body>
<header>
<h1>Learning Git Flow</h1>
</header>
<section>
Coming soon!
</section>
<footer>
2019
</footer>
</body>
</html>

Solving git conflicts

Our next ticket is to update the year in the footer dynamically. It still says 2019.

git flow feature start dynamic-footer-year
<!DOCTYPE html>
<html>
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width" />
- <title>Learning Git Flow</title>
- </head>
- <body>
- <header>
- <h1>Learning Git Flow</h1>
- </header>
- <section>
- Coming soon!
- </section>
- <footer>
- 2019
- </footer>
- </body>
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width" />
+ <title>Learning Git Flow</title>
+ </head>
+ <body>
+ <header>
+ <h1>Learning Git Flow</h1>
+ </header>
+ <section>Coming soon!</section>
+ <footer>
+ <div>
+ <a
+ href="https://medium.com/gumgum-tech/git-and-git-flow-a-guide-871d46a0ebcb"
+ rel="noopener noreferrer"
+ >git and git-flow, a guide</a
+ >
+ </div>
+ <div>
+ <span id="footerYear">2019</span>
+ </div>
+ </footer>
+ <script>
+ function init() {
+ const footerYear = document.getElementById("footerYear");
+ footerYear.innerHTML = new Date().getUTCFullYear();
+ }
+ init();
+ </script>
+ </body>
</html>
git flow feature rebase
Will try to rebase 'dynamic-footer-year' which is based on 'develop'...
First, rewinding head to replay your work on top of it...
Applying: Footer shows current year dynamically
Using index info to reconstruct a base tree...
M index.html
Falling back to patching base and 3-way merge...
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
error: Failed to merge in the changes.
Patch failed at 0001 Footer shows current year dynamically
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Conflicts on index.html
<<<<<<< HEAD=======>>>>>>> branch name
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Learning Git Flow</title>
</head>
<body>
<header>
<h1>Learning Git Flow</h1>
</header>
<section>Coming soon!</section>
<footer>
<div>
<a
href="https://medium.com/gumgum-tech/git-and-git-flow-a-guide-871d46a0ebcb"
rel="noopener noreferrer"
>git and git-flow, a guide</a
>
</div>
<div>
<span id="footerYear">2019</span>
</div>
</footer>
<script>
function init() {
const footerYear = document.getElementById("footerYear");
footerYear.innerHTML = new Date().getUTCFullYear();
}
init();
</script>
</body>
</html>
git add/rm <conflicted files>
git rebase --continue 
git rebase --skip
git rebase --abort
  • You can use git rebase —-skip to ignore the conflicts and continue the rebase; this will probably break your program. I do not recommend it unless you plan on dealing with all of them together instead of individually, which may lead to way more problems.
  • You can leave the detached branch and go back to how everything was before attempting to rebase by running git rebase —-abort.
git flow feature finish -k

Working with Epics

So far, we have worked on simple features that work individually and that after completion, we can merge to master or develop without affecting others’ work.

  • It shows the product title at the top
  • Product description at the bottom
  • Fields: name, email, comment text box, submit button
  • Upon submission, we will send a POST request to an endpoint.
  • Create form UI
  • Create endpoint

Creating sub-task branches

Let’s start by creating the epic ticket just like any other feature:

git flow feature start create-main-content
feature/create-main-content
git flow feature publish
git flow feature start product-information feature/create-main-contentgit flow feature start product-form feature/create-main-contentgit flow feature start product-form-request feature/create-main-content
Switched to a new branch ‘feature/product-information’Summary of actions:- A new branch ‘feature/product-information’ was created, based on ‘feature/create-main-content’- You are now on branch ‘feature/product-information’Now, start committing on your feature. When done, use:git flow feature finish product-information
master <- develop <- feature/create-main-content <- feature/product-information
GitLab’s interface to pick base branches for Merge Requests
git flow feature finish
Summary of actions:- The feature branch ‘feature/product-information’ was merged into ‘feature/create-main-content’- Feature branch ‘feature/product-information’ has been locally deleted; it has been remotely deleted from ‘origin’- You are now on branch ‘feature/create-main-content’

Avoiding conflicts with git rebase — onto

Our project’s latest release includes code that is not related directly to the features we’re developing, but it affects the same section we’re working on. We can update our Epic to get these changes and make sure our new additions are in the right place.

Will try to rebase ‘product-form’ which is based on ‘feature/create-main-content’…Current branch feature/product-form is up to date.
git switch feature/create-main-contentSwitched to branch ‘feature/create-main-content’Your branch is up to date with ‘origin/feature/create-main-content’.
git flow feature rebase
<<<<<<< HEAD
<p>This is a sample project to showcase git to pics.</p>
=======
<div id="product-info">
<h2>Guide</h2>
<ol>
<li>
<a
href="https://medium.com/gumgum-tech/git-and-git-flow-a-guide-871d46a0ebcb"
rel="noopener noreferrer"
>Part 1</a
>
</li>
<li>
<a
href="https://medium.com/@edrpls/git-and-git-flow-part-2-8de67ba2dd31"
rel="noopener noreferrer"
>Part 2</a
>
</li>
</ol>
</div>
>>>>>>> Add product information section%
git switch feature/product-form
git flow feature rebase
<<<<<<< HEAD
<p>This is a sample project to showcase git to pics.</p>
=======
>>>>>>> Add product information section
git log feature/create-main-content
commit 29be90f339f7742513415e2c1c42b952c47dcb96 (origin/feature/create-main-content, feature/create-main-content)
Author: Eder Sánchez <email@example.com>
Date: Mon Mar 29 19:10:16 2021 -0600
Add product information sectioncommit a0001609fbc5d943dd56c24145b9b0de686d5b21 (origin/develop, develop)
Merge: 88753ae 50959e1
Author: Eder Sánchez <email@example.com>
Date: Mon Mar 29 19:45:00 2021 -0600
Merge tag '1.0.1' into develop1.0.1commit 50959e1c105276d793e13d171a0ae3c17f13e409 (tag: 1.0.1, origin/master, origin/HEAD, master)
Merge: 232505f 88753ae
Author: Eder Sánchez <email@example.com>
Date: Mon Mar 29 19:44:56 2021 -0600
Merge branch 'release/1.0.1'commit 88753aed4adcbfb4168a6a74546cfdb02e9fe0b2
Author: Eder Sánchez <email@example.com>
Date: Mon Mar 29 19:42:36 2021 -0600
Add project description (#10)
commit ed1ca5bfdee0568df481285609041e51d5b03884 (HEAD -> feature/product-form)
Author: Eder Sánchez <email@example.com>
Date: Mon Mar 29 19:10:16 2021 -0600
Add product information section
A photo of my dogs to break the huge text block
git rebase —-onto newBase oldBase
git rebase --onto 29be90f ed1ca5bFirst, rewinding head to replay your work on top of it…
commit 29be90f339f7742513415e2c1c42b952c47dcb96 (origin/feature/create-main-content, feature/create-main-content)
Author: Eder Sánchez <email@example.com>
Date: Mon Mar 29 19:10:16 2021 -0600
Add product information sectioncommit a0001609fbc5d943dd56c24145b9b0de686d5b21 (origin/develop, develop)
Merge: 88753ae 50959e1
Author: Eder Sánchez <email@example.com>
Date: Mon Mar 29 19:45:00 2021 -0600
Merge tag '1.0.1' into develop1.0.1commit 50959e1c105276d793e13d171a0ae3c17f13e409 (tag: 1.0.1, origin/master, origin/HEAD, master)
Merge: 232505f 88753ae
Author: Eder Sánchez <email@example.com>
Date: Mon Mar 29 19:44:56 2021 -0600
Merge branch 'release/1.0.1'commit 88753aed4adcbfb4168a6a74546cfdb02e9fe0b2
Author: Eder Sánchez <email@example.com>
Date: Mon Mar 29 19:42:36 2021 -0600
Add project description (#10)
  • Add product form
  • Submit product form payload
git flow feature finishSummary of actions:- The feature branch ‘feature/create-main-content’ was merged into ‘develop’- Feature branch ‘feature/create-main-content’ has been locally deleted; it has been remotely deleted from ‘origin’- You are now on branch ‘develop’

Finding the culprit with git blame

We finished our first “big” feature on time for the new sprint and got a new ticket. We need to add a line to separate the footer from the rest of the content.

git flow feature start footer-divider
git blame index.html
88753aed (Eder Sánchez 2021–03–29 19:42:36 -0600 13) <p>This is a sample project to showcase git to pics.</p>
git switch mastererror: Your local changes to the following files would be overwritten by checkout:index.htmlPlease commit your changes or stash them before you switch branches.Aborting
git stashSaved working directory and index state WIP on footer-divider: 7b0cd34 Add product information and form
git stash popOn branch feature/footer-dividerChanges not staged for commit:
(use “git add <file>…” to update what will be committed)
(use “git restore <file>…” to discard changes in working directory)
modified: index.html

Fixing bugs in production

After stashing our work in progress, we’re able to create a hotfix branch.

git flow hotfix start description-typo
git flow hotfix finish
typo-fix
#
# Write a message for tag:
# description-typo
# Lines starting with ‘#’ will be ignored.
Switched to branch ‘master’
Your branch is up to date with ‘origin/master’.
Merge made by the ‘recursive’ strategy.
index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Switched to branch ‘develop’
Your branch is up to date with ‘origin/develop’.
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
Fatal: There were merge conflicts.
git push # assuming we’re already on developgit switch master # move to mastergit push # push master
major.minor.patch
git tag [tag name]
git tag 1.0.2
git tag1.0.0
1.0.1
1.0.2
description-typo
(END)
git push origin 1.0.2Total 0 (delta 0), reused 0 (delta 0)
To gitlab.com:edr1/git-guide.git
* [new tag] 1.0.2 -> 1.0.2

Undoing git add

Having fixed the issue in production, we can go back to work on the ticket we had:

# go to the branch
git switch feature/footer-divider
# optionally, add fixes
git flow feature rebase
# recover stashed work
git stash pop
git add .
git statusOn branch feature/footer-divider
Changes to be committed:
(use “git restore — staged <file>…” to unstage)
new file: unrelated.md
new file: unrelated_2.md
modified: index.html
new file: unrelated_3.md
git reset unrelated.md unrelated_2.md unrelated_3.md
git statusOn branch feature/footer-divider
Changes to be committed:
(use “git restore — staged <file>…” to unstage)
modified: index.html
Untracked files:
(use “git add <file>…” to include in what will be committed)
unrelated.md
unrelated_2.md
unrelated_3.md
git commit -m”Add divider above footer”# and to publish our branch
git flow feature publish

Other useful git commands

The last ticket marked version 1.1.0(one major, one minor, no patches for the minor version) and our project is public.

It ain’t much but it’s honest work
git shortlogEder Sanchez (6):
Create the README (#1)
Create the index.html page (#3)
Merge branch ‘release/1.0.0’
Merge tag ‘1.0.0’ into develop
Merge branch ‘feature/footer-guide-link’ into ‘develop’
Merge branch ‘feature/dynamic-footer-year’ into ‘develop’
Eder Sánchez (11):
Add link to guide in footer (#5)
Footer shows current year dynamically
Add project description (#10)
Merge branch ‘release/1.0.1’
Merge tag ‘1.0.1’ into develop
Add product information and form
Fix “to pics” typo
Merge branch ‘hotfix/description-typo’
conflict fix
Add divider above footer
Merge branch ‘release/1.1.0’
(END)
git show [reference]:[path to file]
git show develop:index.htmlgit show fe452d2bf4d416:index.html
git show develop:index.html | grep -i email<label for=”email”>Email</label>
<input type=”email” id=”email” name=”email” />
email: elements.email.value,
git show develop:index.html > develop_index.htmlgit statusOn branch master
Your branch is up to date with ‘origin/master’.
Untracked files:
(use “git add <file>…” to include in what will be committed)
develop_index.html
git branch
git branch -d
git branch -D [branch-name]
git cherry-pick [commit hash]
git cherry-pick [first commit hash]..[last commit hash]
git diff
git diff branch1 branch2
git grep [word or expression]
git revert [commit hash]
git revert -n develop~4..develop~1
man git [command]
man git blame

Conclusion

In this part of the guide, we covered some functionality to complement the first part. These are common scenarios that I’ve found working with Git and git-flow over my career and the current workflow we use at GumGum.

  • To work with Epics and Sub-Tasks.
  • To use hotfix branches to fix production bugs
  • How to use various commands for various purposes.

I like some stuff

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store