theme: Next, 1
[.build-lists: true]
- Background
- Internals
- Tips & Tricks
- Best Practices
^
- => Lecture
- => Lecture & Interactive
- => Interactive
- => Lecture
^ Ask this question?
^ What does a VCS do?
[...] a system that records changes to a file or set of files over time -- Scott Chacon & Ben Straub 1
CVS
Perforce
SVN
Mercurial
Git
^ Who has tried what? Later: How they differ
^ published under GNU General Public License version 2 ^ Next Slide: What makes Git different from, for example, SVN
^ What does that mean? For this we have understand:
^
- Central repository = Single source of truth
- Server/Client communication
^ Examples: SVN, CVS, Perforce
^
- Each repository a full backup (with exceptions)
- Communication between repositories
- Possibel to do centralised approach (usual approach)
^ Examples: Git, Mercurial
^ I could bore with commands, but you probably know those already. Let's talk about how Git works internally => Helps a lot for advanced stuff
- Terminology
- Object model
add
reset
commit
merge
^ How to add changes? (Probably familiar with this) Follow up: How does Git track changes?
^
Not only "Distributed"
=> The way Git
thinks about it's files
The major difference [...] is the way Git thinks about its data. -- Scott Chacon & Ben Straub 1
^ Deltas: What changed? Snapshots: Current state Q: Any advantages you can think of?
^ How does Git build this to a commit?
^ Commit -> Tree -> Tree | BLOB Commit: Tree + Parents + Metadata
^ Git is closer to a filesystem then to a classic VCS Next slide: How does Git identify objects?
^ Hash built over all properties of the object (Commit => Author, Committer etc.) You might have heard to never change commits after pushing: Hash changes when properties change
[email protected]:sascha-wolf/git-workshop.git
$ cd git-workshop
$ echo 'Some random text' > my_file
$ git hash-object -w my_file
1a76b8a41993e2c667f5b191fb57abdab2102a8b
$ git cat-file -t 1a76b8a41993e2c667f5b191fb57abdab2102a8b
blob
$ git cat-file -p 1a76b8a41993e2c667f5b191fb57abdab2102a8b
Some random text
^ You can actually find the blob in .git/objects/1a/76b8a41993e2c667f5b191fb57abdab2102a8b Git only uses the content; create an identical file and the hash will be the same
^ Each commit has a reference on it's parent => Single linked list Not really single though ...
^ Q: You want to remove the last commit, how?
#~<N>
^ Better have an example
$ git checkout ancestry
...
$ git log --oneline -1 HEAD
822eca1 Add the number 5 to numbers
$ git log --oneline -1 HEAD^
d4bd446 Add the number 4 to numbers
$ git log --oneline -1 HEAD^^
1b94d52 Add the number 3 to numbers
$ git log --oneline -1 HEAD~2
1b94d52 Add the number 3 to numbers
^ Q: Ask this!
$ ls -l .git/refs/heads
total 32
-rw-r--r-- 1 swolf staff 41 Jan 16 09:06 ancestry
-rw-r--r-- 1 swolf staff 41 Jan 16 07:00 dev
-rw-r--r-- 1 swolf staff 41 Jan 16 07:00 master
-rw-r--r-- 1 swolf staff 41 Jan 16 07:02 waldo-came-and-left
^
All references in .git/refs
:
- branches in
heads
- remote branches in
remotes/<remote-name>
- tags in
tags
^ Q: What do you think is in master?
^
Let us inspect the object!
We can use git cat-file --batch
$ cat .git/refs/heads/master | git cat-file --batch
f20c96538c6dca6fb37e631388814fe941afc2ae commit 540
tree 9ab6d12a4587fb4a02de1b5e745277c6c832cf5a
parent c9866a994539e01938ceec6c75ada013ce456e9b
parent 12e86b3370f931c423022a8c8d7d7fa7413e0bc4
author Sascha Wolf <[email protected]> 1516082444 +0100
committer Sascha Wolf <[email protected]> 1516082444 +0100
gpgsig -----BEGIN PGP SIGNATURE-----
iHUEABEIAB0WIQTQyMji07ff76Vkk26j80vFo8w6AAUCWl2VDAAKCRCj80vFo8w6
AOqtAPoCPrGCN1QZKKGmlqZu43n824v2wviWbUujd9CBwuUURQD/dn2EJ2zHi+zQ
qBKm1cfsi5vwTiYj31O4UbOZ1rJbW1M=
=vi7g
-----END PGP SIGNATURE-----
Merge branch 'dev'
^ Q: What do you think is HEAD? Q: Have you ever seen "detached HEAD"?
$ cat .git/HEAD
ref: refs/heads/master
$ git checkout --detach master
...
$ cat .git/HEAD
f20c96538c6dca6fb37e631388814fe941afc2ae
^
- Reference onto a branch
- Reference onto a commit (detached HEAD)
^ Q: How does a merge differ from a usual commit?
$ git log --decorate --graph --oneline
* f20c965 (origin/master, master) Merge branch 'dev'
|\
| * 12e86b3 (origin/dev, dev) Add bar
| * 4043e69 Add some content to foo
|/
* c9866a9 Add foo
$ cat .git/refs/heads/master | git cat-file --batch
f20c96538c6dca6fb37e631388814fe941afc2ae commit 540
tree 9ab6d12a4587fb4a02de1b5e745277c6c832cf5a
parent c9866a994539e01938ceec6c75ada013ce456e9b
parent 12e86b3370f931c423022a8c8d7d7fa7413e0bc4
author Sascha Wolf <[email protected]> 1516082444 +0100
committer Sascha Wolf <[email protected]> 1516082444 +0100
gpgsig -----BEGIN PGP SIGNATURE-----
iHUEABEIAB0WIQTQyMji07ff76Vkk26j80vFo8w6AAUCWl2VDAAKCRCj80vFo8w6
AOqtAPoCPrGCN1QZKKGmlqZu43n824v2wviWbUujd9CBwuUURQD/dn2EJ2zHi+zQ
qBKm1cfsi5vwTiYj31O4UbOZ1rJbW1M=
=vi7g
-----END PGP SIGNATURE-----
Merge branch 'dev'
^ Q: Do you notice something? => Two parents
bisect
--patch
modestash
reflog
rebase
filter-branch
^ Use aliases for intersting command+option combinations
$ git config --global alias.l 'log --decorate --graph --oneline'
$ git l -3
* f20c965 (HEAD -> master, origin/master) Merge branch 'dev'
|\
| * 12e86b3 (origin/dev, dev) Add bar
| * 4043e69 Add some content to foo
|/
^
--global
to put it into your ~/.gitconfig
Search for the first commit which introduces an issue
$ git bisect start
$ git bisect bad <known bad commit>
$ git bisect good <known good commit>
$ git bisect <known bad commit> <known good commit>
^ Exit codes are used 1: bad commit 0: good commit
^ Show the asciinema as demonstration at the end
$ git checkout patch-practice
...
$ git apply patch-practice.diff
...
$ git add --patch # Try to add only the above line!
^
Tip 1: ?
for help
Tip 2: s
for split
^ It's possible to edit things before adding it to the index! => Show it on the example patch
^ Q: Who knows this already?
push
create a stash from current changespop
apply and delete a stashdrop
delete a stash
Use stash@{<n>}
to reference older stashes
^ Q: What rebase do?
git rebase dev feature/login-button
$ git checkout rebase-practice
...
$ git rebase dev
???
^
Huh, seems like we got a conflict ...
foo
was removed but we want to keep it!
Q: What can we do?
We don't want to remove foo
!
$ git rebase --abort
...
$ git rebase --interactive dev
???
^ Q: Do you know why?
^ Q: Why is that bad?
^ Lot's of ways to rewrite history
Allows to rewrite
--env-filter <command>
--index-filter <command>
--msg-filter <command>
--parent-filter <command>
--subdirectory-filter <directory>
--tag-name-filter <command>
--tree-filter <command>
^
Need to remove a sensitive file from all commits?
tree-filter
to the rescue
cherry-pick
: "copy" one+ commits onto the current branchclean
: remove untracked files and folderscommit --amend
: include added changes in last commitgrep
: search pattern in tracked filesworktree
: checkout a reference into another worktree
Best Practices2
^ You can use interactive rebase for "Perfect later"
^ N: Otherwise your colleagues might do this
<Topic|File>: <Short description> (50 characters sort limit)
<More detailed description> (bullet points are fine)
- problem (what is the issue with the current implementation)
- choosen approach with reasoning
- maybe rejected approaches
Add foo
instead of Added foo
^ N: Don't do this