2. Git Part 1: Understand fundamental git approach and philosophy
● Refresher
○ Repos
○ Commits
○ Branches
● Handling concurrent changes
○ merge (what is it?)
○ rebase (what is it?)
● Undoing things
Git Part 2 (next time): Living the git lifestyle
● Remotes (how do they work?)
● Branching strategies (local and remote)
● Merging and rebasing - Understand how to handle concurrent changes
● Best practices
Git Technical Talk … Agenda …
Git Technical Talk Agenda
4. Git fundamentals
Snapshot SnapshotSnapshot
Git tracks things differently from most version control systems
● Instead of change tracking, Git uses the idea of a commits, which can be thought of as pointers to
snapshots of the filesystem
● Commits relate to each other in a “directed graph”
Commit 1 Commit 2 Commit 3
File 1
File 2
File 3
File 1’
File 3
File 1
File 3’
File 2
These snapshots are stored in the .git subdirectory of your projects (the repository)
Git Technical Talk … Refresher …
5. Git approach
Git Technical Talk … Refresher …
How does git track source?
● You checkout the source from the repo, change files in the working directory, stage them to staging area,
and then commit them back to the repo
● These snapshots are stored in the .git subdirectory of your projects
Working
Directory
Staging
Area
Repo (.git)
Checkout from repo
Add to Staging Area
Commit to Repo
Creates the “snapshot” or
commit
6. Commit
1840be
This creates a commit: Commits point to a snapshot of all the repository
Snapshot
test.txt
Git approach
Git Technical Talk … Refresher …
7. Commit
1840be
Branches are just “labels” that point to a commit
master
Snapshot
test.txt
Git branches
Git Technical Talk … Refresher …
8. Commit
1840be
Commit
927627
master
Note that there’s nothing special about master – it’s just the default name that git uses for the 1st
branch
Git commits
Git Technical Talk … Refresher …
New commits create a pointer to the
previous commit and moves the current
branch label to the new commit
9. Commit
1840be
Git branch just makes a new pointer that points to the current commit
git branch test
Commit
927627
test
master
Git branches
Git Technical Talk … Refresher …
10. Commit
1840be
HEAD is a special pointer that identifies the branch that will be updated with the next commit
Commit
927627
test
master
HEAD
Git branches
Git Technical Talk … Refresher …
11. Commit
1840be
Git checkout changes the current branch (i.e. moves HEAD to the commit the branch points to) and updates
the working directory with the snapshot of that commit
Commit
927627
test
master
HEAD
Git checkout
Git Technical Talk … Refresher …
12. Commit
1840be
New commits move the branch pointer that HEAD is pointing to… for example on the branch test...
Commit
927627
test
master
HEAD
Commit
230364
Git branches
Git Technical Talk … Refresher …
14. Commit
1840be
Let’s checkout master…
$ git checkout master
Switching to branch ‘master’
Commit
927627
test
master
Commit
230364
HEAD
Quiz: Why doesn’t commit 230364 show up in the git log result?
Git concurrent changes
Git Technical Talk … Concurrent Changes …
15. Commit
1840be
Now let’s change test.txt on master
Commit
927627
test
master
Commit
230364
HEAD
Commit
217f1a
Git concurrent changes
Git Technical Talk … Concurrent Changes …
16. What to do when the tree diverges?
There’s two ways to approach the problem:
• Merge
• Rebase
Merge or rebase
Git Technical Talk … Concurrent Changes …
18. Commit
1840be
Git merge combines changes (using the Linux diff utility) from one branch into another and creates a new commit
• Switch to branch you want to merge into
• Use git merge <branch to merge from>
Commit
927627
test
master
Commit
230364
HEAD
Commit
217f1a
New
commit
merge
Git merge
Git Technical Talk … Concurrent Changes …
19. Let’s try it …
Git couldn’t resolve the conflict – so it wrote this into test.txt
This is the Linux diff format
Learn a good 3 way merge tool to resolve… (Intellij Idea, kdiff3, Beyond Compare, etc.)
Git merge
Git Technical Talk … Concurrent Changes …
21. Commit
1840be
We don’t need test anymore, let’s delete it
$ git branch -d test
Deleted branch test (was 2303644).
Commit
927627
master
Commit
230364
HEAD
Commit
217f1a
Commit
df0a2e
YES DELETE IT! This just removes the test pointer - not the
commits!
Git merge
Git Technical Talk … Concurrent Changes …
22. You can see a graph view with the --graph option
Notice you didn’t lose any commit
history by deleting the branch, just
the pointer
Now you can go happily along with your life….
Git merge
Git Technical Talk … Concurrent Changes …
24. What a rebase does:
1. Finds common ancestor between the
branches in question
2. Generates a linux diff of each commit
since the common ancestor
3. Replays those changes onto the
chosen branch
This is effectively “rewriting history” to
make it look like the changes originally
occurred on the selected branch
Stepping back in time to solve the last divergence with a rebase
master
HEAD
Commit
1840be
Commit
927627
test
Commit
230364
Commit
217f1a
Git Technical Talk … Concurrent Changes …
26. Git rebase
“git rebase master”
● This is ultimately saying, “I want to take all the
changes that have happen on test since it
branched off of master and replay them onto the
latest master, in test”
*In this case*, rebase saw the conflict and forced a
manual resolution on us.
Again, 3-way merge tool to the rescue - (or vi :))
Git Technical Talk … Concurrent Changes …
28. Merge to master
master
HEAD
Commit
1840be
Commit
927627
test
Commit
13856f
Commit
217f1a
Now, let’s get it onto master:
$ git checkout master
Switched to branch 'master'
$ git merge test
Updating 217f1ad..13856ff
Fast-forward
test.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Note - the log commit message for 13856f - Where did it come
from?
230364 - the message from the original commit on test!!!
Git Technical Talk … Concurrent Changes …
30. Fast-forward merge
Commit
1
Commit
2
master
HEAD
Commit
3
Commit
4
test
A fast-forward merge occurs when merging into a
parent branch when there are no additional commits on
the parent branch
git checkout master
git merge test
Thus, master is effectively “fast-forwarded” to
point to the same commit as test
● No new commit is made
● This happens by default
Git Technical Talk … Concurrent Changes …
31. Forcing a non-fast-forward merge
Commit
1
Commit
2
master
HEADCommit
3
Commit
4
You may want to explicitly show the merge in the
history, even if it is a candidate for a fast-forward:
git checkout master
git merge test --no-ff
Now, there is a new commit dedicated to
reflecting the merge
Commit
5
Git Technical Talk … Concurrent Changes …
34. Git Technical Talk … Undo …
Undoing things in git: revert, reset and checkout
3 main ways of fixing commit mishaps:
● git revert
○ Creates a new commit which undoes a specified commit - “adds to history”
○ Can revert to any commit in the history, not just the last one
● git reset
○ “resets” the current branch HEAD to a specified commit
○ Effectively sets the entire local state of the repo to a snapshot of your last commit
○ Can be used to remove all history of a commit - effectively “rewrites history”
○ Has 3 options: soft, mixed (default), hard - more on these
● git checkout
○ Can be used to manually pull individual files from a commit
35. Simple program to sort a string array, with unit test
Setting the stage
Commit
30508d
master
HEAD
Git Technical Talk … Undo …
36. Make a minor change to the sort method:
● git commit -am "Printed list after sorting”
Setting the stage
Commit
30508d
master
Commit
5a7072
HEAD
Git Technical Talk … Undo …
37. Adding even more cities to the test: git commit -am "Enhanced test set"
Setting the stage
Commit
30508d
master
Commit
5a7072
HEAD
Commit
d34d30
Git Technical Talk … Undo …
38. Whoops - we have a bad commit, and there are other commits after it
Setting the stage
Commit
30508d
master
Commit
5a7072
HEAD
Commit
d34d30
Git Technical Talk … Undo …
39. revert adds a new commit to the history
● Allows you to “go back in time” to remove a
commit, but keeps all the previous history
● In this case, the bad commit is effectively
gone, but full history is retained
● SAFE to do!!!
● Reflects reality
Git revert
Commit
30508d
master
Commit
5a7072
HEAD
Commit
d34d30
Commit
a807cb
This commit is still in the
history, but effectively removed
in a807cb
Git Technical Talk … Undo …
40. Git reset
Reset can change 3 things:
● HEAD (i.e., what revision/commit you’re currently working on)
● staging area/index
● working directory
3 main flavors of reset, in order of destructiveness:
● git reset --soft
○ Only changes HEAD
● git reset --mixed (this is default)
○ Changes head, AND “unstages” the changed files
● git reset --hard
○ Changes HEAD, unstages the changed files and removes all non-committed changes
from working directory
Git Technical Talk … Undo …
41. Let’s start again with the same example - but do a reset this time
Setting the stage - again
Commit
30508d
master
Commit
5a7072
HEAD
Commit
d34d30
Git Technical Talk … Undo …
42. Staging Area
soft reset sets your repo up to look just like it did at the given commit
● HEAD and the branch we’re on (master) now point to the selected commit
● --soft leaves all the changes between d34d30 and 30508d staged (in the
index/staging area)
● Would require manually fixing the change, then re-adding id
● a commit at this point would end up leaving the resulting files effectively
unchanged, but REWROTE HISTORY
○ Not the desired effect in this case
Git reset --soft
Commit
30508d
master
Alphabetical
Sorter.java
HEAD
SorterTest
.java
Git Technical Talk … Undo …
43. Working Directory
mixed reset sets your repo up to look just like it did at the given commit
● HEAD and the branch we’re on (master) now point to the selected commit
● --mixed leaves all the changes between d34d30 and 30508d UN-staged (in
the working directory)
● At this point, we can manually unmake the non-desired changes
● Not much different than soft, still requires manual resolution
Git reset --mixed
Commit
30508d
master
Alphabetical
Sorter.java
HEAD
SorterTest
.java
Git Technical Talk … Undo …
44. hard reset makes everything exactly like nothing none of the commits after the
selected commit ever existed in the log
● HEAD and the branch we’re on (master) now point to the selected commit
● There are no staged changes - everything is gone
● We lost the test case changes
● With no remote to pull from, it’s all gone
Git reset --hard
Commit
30508d
master
Commit
5a7072
HEAD
Commit
d34d30
Git Technical Talk … Undo …
Is that what we really wanted???
45. In any of the reset based fixes:
● Manual resolution required - re-commit resulted in the desired codebase
● “Re-wrote history” - dangerous
Git reset requires manual resolution in this case
Commit
30508d
master
Commit
b793b8
HEAD
Git Technical Talk … Undo …
46. Git reflog is:
● A record of every HEAD move
● A local only way to undo the “oops”
● Example is restoring HEAD to “where it was 1
commit ago”
● Can be used with a “reset --hard” to undo
rebases/merges gone bad (as long as you
haven’t pushed it)
Git reflog can undo a bad reset
Commit
30508d
master
Commit
5a7072
HEAD
Commit
d34d30
Git Technical Talk … Undo …
47. Git reflog can undo a bad merge
Commit
30508d
master
Commit
5a7072
HEAD
Commit
d34d30
Commit
a104c3
Developer X went in and changed the sorter
to a reverser on a new branch, then merged it
into master:
● git checkout -b feature
● <modify file, do something bad>
● git commit -am "Change from sorting to
reversing"
● git checkout master
● git merge feature
feature
Oops - we don’t want that feature in master at all...
Git Technical Talk … Undo …
48. Git reflog can undo bad a merge
Commit
30508d
master
Commit
5a7072
HEAD
Commit
d34d30
Commit
a104c3
We can get master back to a clean state with a hard
reset against the reflog:
● git reset --hard HEAD@{1}
We then have a chat with developer X and make
him/her fix their work before merging again
This works even when the merge interleaves commits
into the history!
Remember: local only
feature
Git Technical Talk … Undo …
49. One other approach: git checkout
● Allows you to checkout a specific file from
a specific commit without modifying
HEAD
● Great for individual files, not good for
larger changes
git checkout
Commit
30508d
master
Commit
5a7072
HEAD
Commit
d34d30
Commit
ef3002
Git Technical Talk … Undo …
50. git tags
There are 2 main flavors of tags in git:
● lightweight: “git tag <tag_name>”
○ This is essentially the same thing as a branch, but doesn’t move
● annotated: “git tag -a <tag_name> -m “Tag message”
○ Essentially a more verbose, “permanent” tag
○ This includes a commit message, the person who tagged it, email, date
Note that tags must be pushed if working with a remote repo, or they only exit locally:
● git push origin <tagname>
Git Technical Talk … Undo …
52. Remotes are a link to another repo in a different location
• A remote is simply a link to another git repo
• A remote repository can exist in the following locations:
– On a remote HTTP server
– On a remote SSH server
– Somewhere else on your machine (different local directory)
There’s nothing special about a remote… I’ll prove it…
Let’s make a test repo
Git Technical Talk … Remotes …
53. • Now, let’s make another...
• We can simply add the test repo as a remote…
• That’s it! Now we can interact with it
– “test” is now the name for this remote which is associated with the test2 repo, similar to what “origin”
is with a clone
Remote example
Git Technical Talk … Remotes …
54. Remote example
Now, let’s fetch the commits from the
remote:
test/master
HEAD
Commit
8c5afe
master
Commit
4716f9
Git Technical Talk … Remotes …
Now, checking out each branch shows
only the files associated with them
individually
55. Remote example
Just like before we can merge (or rebase) together
test/master
HEAD
Commit
8c5afe
master
Commit
4716f9
Commit
d960f4
Git Technical Talk … Remotes …
56. Clone is just a little syntactic sugar for what
we just did…
/Users/jleisy/test
Remote clone
Clone essentially makes a remote called “origin”
and pulls everything
master
Commit
8c5afe
/Users/jleisy/test3
origin/master
Commit
8c5afe
“origin” refers to this repo
master
HEAD
origin/HEAD
HEAD
Git Technical Talk … Remotes …
57. /Users/jleisy/test
Remote updates
Let’s make some updates to both and see what happens...
master
Commit
8c5afe
/Users/jleisy/test3
origin/master
Commit
8c5afe
“origin” refers to this repo
master
HEAD
origin/HEAD
HEAD
Commit
9bc8d8
Git Technical Talk … Remotes …
58. /Users/jleisy/test
“Gitting” remote updates (pun intended…)
master
Commit
8c5afe
/Users/jleisy/test3
Commit
8c5afe
“origin” refers to this repo
master
HEAD
HEAD
Commit
a36d94
Git Technical Talk … Remotes …
git fetch will update the repo with the commits only...
Commit
a36d94
origin/master
origin/HEAD
59. /Users/jleisy/test
Pull
git pull will merge all the changes from the remote branch
master
Commit
8c5afe
/Users/jleisy/test3
origin/master
Commit
a36d94
“origin” refers to this repo
master
HEAD
origin/HEAD
HEAD
Commit
a36d94
Commit
8c5afe
Git Technical Talk … Remotes …
pull is syntactic sugar for:
• git fetch
• git merge FETCH_HEAD
61. There are two main types of git workflows
There are 2 main flavors of workflows: centralized and decentralized
● The actual examples of workflows are many and varied
● Centralized refers to having one central repo that everyone clones from and pushes to
● Decentralized means having multiple remote repos
○ One is the “primary” that builds are done from
○ Developers have their own remote repos that are public
Images courtesy of https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows
Git Technical Talk … Workflows …
Centralized De-centralized
63. Best Practices for Crederans
We have derived some “best practices”
The 2 Most Important best practices are:
1. Listen to your architects/team leads
○ Not all of these best practices will jive with what you have in place for every client situation
2. Adhere to client/customer standards
○ Many clients will have an already-established approach to many of these things
The basic knowledge here should help you:
○ Understand what you’re doing with git
○ Provide some defenses to keep things from going wrong
Git Technical Talk … Best Practices …
64. Command line usage
Command line
● Use it!
Stop using SourceTree/Eclipse/Idea/etc plugins until you completely understand everything they’re
doing
● If you don’t fully understand a button/feature, don’t use it!
○ Stop, learn what it’s doing under the covers first
○ SourceTree will show you what commands it's going to run
● If you’re not sure if you understand what the GUI tool is doing, stop and do it by hand
● GUI Tools can be used when they increase velocity, once you understand what they do
○ Many seasoned developers still stick with the command line
Git Technical Talk … Best Practices …
65. Commits
What makes a good commit?
● Ideally, each commit is an atomic unit of work which could go to test/production
○ Clean, commented, tested, as ready to ship as possible
○ Test before committing - if it's not ready, don’t commit!
○ Can commit to a local-only branch, which you can squash later (before pushing)
● What about “Commit Early and Often”?
○ That means work with smaller features/units of work, not partially working or untested
commits
Bad practice: committing non-working code throughout or at the end of the day
● Remember, a commit is a snapshot of the entire repo
○ Do not want that snapshot to reflect something in a known-bad state
○ Ask yourself this: would you want to push non-working/incomplete code to a public repo?
Git Technical Talk … Best Practices …
66. Bad practice: committing for the purpose of “backing up your work”
● Commits are not there to serve as backups
○ Backups can be in private repo on the server
○ If you need to do this - use a private repo and non-published branch (Decentralized Workflow)
○ Use squash before sending it out
Commits
Git Technical Talk … Best Practices …
client/repoX jgoth/repoX
jgoth/repoX
Server
Local
Fork
Pull Request
Clone
Push
67. Commits
Utilize meaningful commit messages
● Good:
○ “Fixed defect XYZ”
○ “Implemented webhook push notifications”
● Bad:
○ “Fixed stuff”
○ “Cleaned up code”
○ “I did something totally awesome by changing lines 172-193 from using a complex for loop
to a super awesome lambda expression, which Joe and Sally were super impressed with.
I really want to show it to the entire world, so please check out how awesome it is; this
allows me to really clean up the code and improve performance”
Git Technical Talk … Best Practices …
68. Recommended Workflow
Credera recommended git workflow:
● Don’t work directly on “published” branches (i.e. branches that other people push and pull from
or that you build from)
○ Clone and use a private branch
○ Make your changes on that branch
○ Merge or rebase onto public branch
Why?
● Gives a “clean” place for updates from the remote
● Allows you to make mistakes, reset (reflog) and start fresh in a clean area
● The following pages show an example...
Git Technical Talk … Best Practices …
70. Recommended Workflow Example
Git Technical Talk … Best Practices …
A B C
A B C
Server
Clone
Steps:
1. Create a branch from master, check it out,
do your work (test!)
D
master
master
featureXYZ
71. Recommended Workflow Example
Git Technical Talk … Best Practices …
A B C
A B C
Server
Clone
Steps:
1. Create a branch from master, check it out,
do your work (test!)
2. (Optional) Push your branch to remote repo
D
master
master
featureXYZ
D
E
featureXYZ
72. Recommended Workflow Example
Git Technical Talk … Best Practices …
A B C
A B C
Server
Clone
Steps:
1. Create a branch from master, check it out,
do your work (test!)
2. (Optional) Push your branch to remote repo
3. Check out master, get up-to-date
D
master
master
featureXYZ
D
E
E
featureXYZ
73. Recommended Workflow Example
Git Technical Talk … Best Practices …
A B C
A B C
Server
Clone
Steps:
1. Create a branch from master, check it out,
do your work (test!)
2. (Optional) Push your branch to remote repo
3. Check out master, get up-to-date
4. Merge your changes into master (test!)
D
master
master
featureXYZ
D
E
E
F
featureXYZ
74. Recommended Workflow Example
Git Technical Talk … Best Practices …
A B C
A B C
Server
Clone
Steps:
1. Create a branch from master, check it out,
do your work (test!)
2. (Optional) Push your branch to remote repo
3. Check out master, get up-to-date
4. Merge your changes into master (test!)
5. Push updates to master
D
master
master
featureXYZ
D
E
E
F
F
featureXYZ
75. Recommended Workflow Example
Git Technical Talk … Best Practices …
A B C
A B C
Server
Clone
Steps:
1. Create a branch from master, check it out,
do your work (test!)
2. (Optional) Push your branch to remote repo
3. Check out master, get up-to-date
4. Merge your changes into master (test!)
5. Push updates to master
6. Delete your branch (delete remote too!)
D
master
master
D
E
E
F
F
76. Recommended Workflow
● Consistent with what most respected organizations do (for example, to contribute to Fedora):
Reference: https://wiki.duraspace.org/display/FCREPO/Git+Guidelines+and+Best+Practices
● Again, you may need to vary based on client preference - listen to your architect
Git Technical Talk … Best Practices …
77. Rebase
Rebase rules:
1. Do not (ever) rebase commits that you have pushed to a remote repository
2. Do not (ever) rebase commits that you have pulled from a remote repository
Remember, rebasing rewrites history
● Even when done properly, rebasing changes the SHA commit hashes for commits
● If someone else has access to this history, you’re going to have a very, very bad time
Rebasing can be a great way to keep commit history clean in a local, private branch
● The recommended workflow (local branch) makes this easy
○ You can rebase your local branch onto master as you work
○ You can squash merge your smaller (still buildable, testable) commits as a single commit
back onto master
Git Technical Talk … Best Practices …
78. Rebase
Avoid “git pull --rebase”
● This is often recommended online as a way to do work on a single branch
● This rebases all of your current work onto the current HEAD
○ i.e., save off a patch of all your current commits in a temp area
○ pull, update HEAD
○ re-apply your current commits
● It is possible for conflicts to not be automatically cleanly applied
● Not a clean way to “undo” if this happens (have to use “git reset”)
● Dangerous - make sure you really know what you are doing
Git Technical Talk … Best Practices …
79. Separation of concerns
Separation of concerns: deployment and code management
Don’t combine deployment and code management
Use tags (not branches) to identify builds
● Tags will give you what you need to be able to deploy/reproduce a build
● Separate branches do not need to be kept for every deployment to production (messy)
● Remember - you can checkout a commit (tag) not just a branch
Example:
1. Tag a release point
2. Build from the tag
3. Push it (into something like Artifactory)
4. Deploy from remote/external/segregated repository (from something like Artifactory)
Git Technical Talk … Best Practices …
80. Workflow design
When you are in a position to design a workflow, Keep It Simple
● Stick with the simple approach until there is a really good reason to change
● A “really good reason” is not something that just happens once
Example:
1. Have a “golden” repo (master/preprod/etc)
2. Everyone clone
3. Developers make a local branch
4. Developers make changes in local branches
5. Developers squash merge changes into local copy of golden repo
6. Push back to golden repo
7. Profit!
● Manage releases with tags
● Show production support as a different tag merged in
● Works well for teams up to ~10 people, all working on the same baseline
Git Technical Talk … Best Practices …
81. Workflow design
Cases where more complex workflows can be appropriate:
● Multiple, long running projects/features with different timelines
○ Branches for features are good in this case
○ You can still use the recommended approach (develop on private branches)
○ Frequently pull
○ Again, you may have to follow customer standards…
● Customers don’t want many people doing merges
○ Everyone have their own remote repo forked from primary
○ Clone local
○ Add “gold remote”
○ Make a local branch
○ Make your changes
○ Do a pull from gold/master
○ Merge in your changes
○ Push to your remote (origin/master)
○ Do a merge/pull request from there to gold/master
Git Technical Talk … Best Practices …
82. Best practices final thoughts
● Don’t commit IDE-specific files
○ Doesn’t support an IDE-agnostic environment
○ Causes issues for others - can contain developer-specific, non-project related
configuration information
○ If you must share them, do so outside of the source code repository
● Don’t put usernames and passwords into git
○ Exception: You have a special, separate, tightly-secured, repo for this purpose only
■ This special repo contains configuration data, not code
● Clean up after yourself
○ Remove unneeded branches: push origin --delete <branch>
■ Won’t delete the commits if they exist and are referenced elsewhere, such as the
branch you (squash) merged them into
Git Technical Talk … Best Practices …
83. Best practices final thoughts
● Ignore what you read online about git best practices unless you know the author
○ Lots of bad “best practices” exist online
○ Many are working on very simple projects or very small teams
● Windows users: git config --global core.autocrlf true
○ This causes git to convert source code files to CRLF-based line endings on checkout
○ git will then convert them to LF when checking in
○ Can substantially reduce headache when not all developers are on windows
● Linux/Unix users: git config --global core.autocrlf input
○ This will cause source files to be converted to LF-based line endings if there are any
CRLF-based lines upon check-in
○ This can be used to “fix” CRLF-based line endings when working with windows-based
team members
Git Technical Talk … Best Practices …