Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff
Transcript of Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff
![Page 1: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/1.jpg)
NICOLA PAOLUCCI • DEVELOPER INSTIGATOR • ATLASSIAN • @DURDN
Advanced Git TechniquesSubtrees, grafting and other fun
![Page 2: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/2.jpg)
Get more out of your version control.
![Page 3: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/3.jpg)
Today we’ll cover some powerful Git goodies
Interactive stagingPainless sub-projects Collating historyInteractive commits are an amazing tool at your disposal as you work on complex code changes
You can use git subtree to handle external libraries in a clean and efficient way
Joining together history of your projects using git replace is useful when migrating to Git
![Page 4: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/4.jpg)
git subtreeExtract project
Alternative to git submodule to handle external dependencies.
Inject dependencyIt allows you to inject an external project into a sub-folder
Introduced in 1.7.11
It can be also used to extract a sub-folder as separate project
![Page 5: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/5.jpg)
Clean integration pointsStores in regular commitsNo training
When and why is git subtree a great choice
Does not require your entire team to be trained in the use of the command
The command stores the external dependency in regular Git commits. Squashing the history optionally.
It makes it easy to see when integrations happened and makes it easy to revert them.
![Page 6: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/6.jpg)
Syntax to inject a project
Command to inject project
git subtree add \ --prefix target-folder \ https://bitbucket.org/team/sub.git \ master --squash
Folder where to insert code
Repository URL
v1.1
![Page 7: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/7.jpg)
Under the hood of git subtree
commit ab54c4e0b75c3107e3e773ab9b39268abddca002Author: Nicola Paolucci <[email protected]>Date: Tue Sep 29 15:27:35 2015 +0200
Squashed ‘src/sub-project‘ content from commit df563ed git-subtree-dir: src/sub-project git-subtree-split: df563ed15fa6…6b2e95d3
![Page 8: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/8.jpg)
Result of git subtree add
commit 8fb507baf7b270c30c822b27e262d0b44819b4c5Merge: 606cd3e ab54c4eAuthor: Nicola Paolucci <[email protected]>Date: Tue Sep 29 15:27:35 2015 +0200
Merge commit 'ab54c4e0b75c3107e3e773ab9b39268abddca002' as '.vim/bundle/fireplace'
commit ab54c4e0b75c3107e3e773ab9b39268abddca002Author: Nicola Paolucci <[email protected]>Date: Tue Sep 29 15:27:35 2015 +0200
Squashed '.vim/bundle/fireplace/' content from commit df563ed git-subtree-dir: .vim/bundle/fireplace git-subtree-split: df563ed15fa685ce2508bf16b3ca7e176b2e95d3
![Page 9: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/9.jpg)
To keep the sub-project up to date
git subtree pull \ --prefix target-folder \ https://bitbucket.org/team/sub.git \ master --squash
Command to pull project
Folder where to insert code
Repository URL
v1.5
![Page 10: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/10.jpg)
Under the hood of git subtree
commit ab54c4e0b75c3107e3e773ab9b39268abddca002Author: Nicola Paolucci <[email protected]>Date: Tue Sep 29 15:27:35 2015 +0200
Squashed ‘src/sub-project‘ content from commit df563ed git-subtree-dir: src/sub-project git-subtree-split: df563ed15fa6…6b2e95d3
![Page 11: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/11.jpg)
Find the symbolic ref matching a hash (sha-1)
sha-1 of last commit pulled
Git plumbing to list all remote refs
Repository URL
git ls-remote https://bitbucket.org/team/sub.git | grep df563eddf563ed15fa685ce2508bf16b3ca7e176b2e95d3 v1.15eaff1232acedeca565er7e1333234dacccebfff v1.5
git ls-remote https://bitbucket.org/team/sub.git | grep <sha-1>
![Page 12: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/12.jpg)
Aliases to make your life easier!
[alias] sba = "!f() { git subtree add --prefix $2 $1 master --squash; }; f" sbu = "!f() { git subtree pull --prefix $2 $1 master --squash; }; f"
Alias section of your .gitconfig
http://bit.do/git-aliases
![Page 13: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/13.jpg)
How to use the aliases
git sba <repo URL> <destination-folder>
git sba https://bitbucket.org/team/sub.git src/sub
![Page 14: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/14.jpg)
When everyone in the team must work on
sub-projects
When you have constant updates to your dependencies
When you have many dependencies
When NOT to use git subtree
![Page 15: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/15.jpg)
For complex project dependencies Use a dependency tool. Really.
![Page 16: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/16.jpg)
Alternatives? Read my rant on project dependencies
http://bit.do/git-dep
![Page 17: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/17.jpg)
How to extract a projectLet’s learn how to use subtree split
![Page 18: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/18.jpg)
Git subtree to extract a project
Command to split out project
git subtree split \ --prefix my/project/ \ --branch extracted
Folder prefix to extract
where we store it
![Page 19: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/19.jpg)
Push to new remote
We can remove the contents of the folder from the repo
Import extracted branchInitialise a new repo and import the extracted branch
Remove from old repo
After we imported the code we can push it to a new repository
git rm -rf my/project
git initgit pull ../path/ extracted
git remote add origin …git push origin -u master
![Page 20: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/20.jpg)
Interactive commitSplitting commits semantically in flight!
![Page 21: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/21.jpg)
Fine grained control on your commits
Knowing this technique frees you from worrying
about what to do first
Atomic commits make your changes readable
Why split changes interactively?
![Page 22: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/22.jpg)
We modify a single file (README) in 3 parts
# Title
Content of my article
## Subtitle second heading
Some more paragraph content
## Conclusions
Here are your conclusions
![Page 23: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/23.jpg)
We modify a single file in 3 different parts
[:~/p/demo] master(+3/-0) ± git diff@@ -1,11 +1,14 @@ # Title Content of my article+Adding a second line to Title. ## Subtitle second heading Some more paragraph content+Adding another line to Subtitle 1 ## Conclusions Here are your conclusions+Adding to the Conclusions.
![Page 24: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/24.jpg)
To split those changes in separate commits:
git commit --interactive
staged unstaged path 1: unchanged +3/-0 README.md
*** Commands *** 1: status 2: update 3: revert 4: add untracked 5: patch 6: diff 7: quit 8: helpWhat now>
![Page 25: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/25.jpg)
Overview of interactive staging
revert
The status of the files, whether they are staged or unstaged.
updateChoose which files to add to the staging area
status
Undo any action done previously in this session.
![Page 26: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/26.jpg)
Overview of interactive staging [2]
add untracked
Check the unstaged or staged changes in the workspace.
patchAdd parts of a file to the staging area. This allows you to split commits.
diff
Add new untracked files to the repository.
![Page 27: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/27.jpg)
I finally hit “p” for patch, select the file and ENTER:
What now> p staged unstaged path 1: unchanged +3/-0 README.mdPatch update>> 1 staged unstaged path* 1: unchanged +3/-0 README.mdPatch update>>
![Page 28: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/28.jpg)
I finally hit “p” for patch, select the file and ENTER:
@@ -1,11 +1,14 @@ # Title Content of my article+Adding a second line to Title. ## Subtitle second heading Some more paragraph content+Adding another line to Subtitle 1 ## Conclusions Here are your conclusions+Adding to the Conclusions.Stage this hunk [y,n,q,a,d,/,s,e,?]?
Stage this hunk?!?!
![Page 29: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/29.jpg)
![Page 30: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/30.jpg)
A hunk is just a piece of text in a larger file. Diff and patch commands tend to understand changes by clustering them in blocks of continuous text.
“
”
![Page 31: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/31.jpg)
![Page 32: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/32.jpg)
If the default hunk size is too big, you can split it:
Stage this hunk [y,n,q,a,d,/,s,e,?]? sSplit into 3 hunks.@@ -1,7 +1,8 @@ # Title Content of my article+Adding a second line to Title. ## Subtitle second heading Some more paragraph contentStage this hunk [y,n,q,a,d,/,j,J,g,e,?]?
![Page 33: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/33.jpg)
Let’s stage this hunk, or add it to the staging area:
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y@@ -4,8 +5,9 @@ ## Subtitle second heading Some more paragraph content+Adding another line to Subtitle 1 ## Conclusions Here are your conclusionsStage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]?
![Page 34: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/34.jpg)
Now so skip all the rest pressing “q” twice:
![Page 35: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/35.jpg)
The result is a neat new commit and the rest left:
14a0be4 [4 minutes ago] (HEAD -> master) Add content to Title [Nick]
git diffdiff --git i/README.md w/README.mdindex fc26295..0ef85c4 100644--- i/README.md+++ w/README.md@@ -6,7 +6,9 @@ Adding a second line to Title. ## Subtitle second heading Some more paragraph content+Adding another line to Subtitle 1 ## Conclusions Here are your conclusions
![Page 36: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/36.jpg)
When you need help just press “?”Stage this hunk [y,n,q,a,d,/,s,e,?]? ?y - stage this hunkn - do not stage this hunkq - quit; do not stage this hunk or any of the remaining onesa - stage this hunk and all later hunks in the filed - do not stage this hunk or any later hunks in the fileg - select a hunk to go to/ - search for a hunk matching the given regexj - leave this hunk undecided, see next undecided hunkJ - leave this hunk undecided, see next hunkk - leave this hunk undecided, see previous undecided hunkK - leave this hunk undecided, see previous hunks - split the current hunk into smaller hunkse - manually edit the current hunk? - print help
![Page 37: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/37.jpg)
Collating History
![Page 38: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/38.jpg)
Cross VCS mergesUnify two reposFast migration from svn
Why collate history?
Migrate immediately from Subversion, attach the earlier history after the migration.
You have two repositories that should actually be only one.
You need to perform Subversion merges in a Git branch
![Page 39: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/39.jpg)
One relevant example: Linux kernel
Today use git replace
The entire history of the Linux kernel is split over three different repos.
Originally in GraftsWhich are local pair of ids connecting a commit id (SHA-1) to the next
Linux kernel is split
Available in the stock git distribution since version 1.6.5
![Page 40: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/40.jpg)
git replace is capable to replace any object with any other object. It tracks these swaps via refs which you can push and pull between repositories.
“
”
![Page 41: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/41.jpg)
git replace in practice
shallow
first
last
legacy
shallow clone with cut history
git replace first last
![Page 42: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/42.jpg)
First commit of restarted repo
git checkout -b shallow origin/shallowgit log --max-parents=0 master
git tag 56eacf first -m”Tag… commit”
shallow
first
![Page 43: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/43.jpg)
Last commit of legacy repo
git checkout -b legacy origin/legacygit rev-parse --verify legacy
git tag 84abb last -m”Tag… commit”
last
legacy
![Page 44: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/44.jpg)
git replace in practice
shallow
first
last
legacy
shallow clone with cut history
git replace first last
![Page 45: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/45.jpg)
Replacements are persisted
cat .git/refs/replace/56eac…7cc84abb39d9aab234dfba2e41f13f693fa5edbfe22
git push origin ‘refs/replace/*’
![Page 46: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/46.jpg)
If you want to make the git replace changes permanent and free the team from pulling those refs, do a final pass usinggit filter-branch
“
”
![Page 47: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/47.jpg)
Go forth and enrich your Git experience
![Page 48: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/48.jpg)
Thank you!
NICOLA PAOLUCCI • DEVELOPER INSTIGATOR • ATLASSIAN • @DURDN
Twitter: @durdn
![Page 49: Advanced Git Techniques: Subtrees, Grafting, and Other Fun Stuff](https://reader031.fdocuments.us/reader031/viewer/2022021919/587960481a28ab1e388b6235/html5/thumbnails/49.jpg)
• GIF backdrops taken from giphy.com • Icons from thenounproject.com credits below
Image credits