Workshop
Antoine Froger
(survival kit)
The Working directory
The Index (or stage)
The HEAD
Sandbox
Proposed next commit snapshot
Last commit snapshot
$ git branch * master rebase-i-demo untracked-demo
$ git branch -a
* master
rebase-i-demo
untracked-demo
remotes/origin/HEAD -> origin/master
remotes/origin/master
// Rename branch
$ git branch -m branch-old-name branch-new-name
// Rename current branch
$ git branch -m branch-new-name
$ git branch -a
master rebase-i-demo untracked-demo
* branch-new-name
$ git branch -d obsolete-branch
// equivalent to git branch --delete
error: The branch 'obsolete-branch' is not fully merged.
If you are sure you want to delete it, run 'git branch -D
obsolete-branch'
$ git branch -D obsolete-branch // Shortcut for --delete --force Deleted branch obsolete-branch (was 12345)
Displays some information about the last commit
$ git branch -vv
* master a3d3414 [origin/master] Add homepage
rebase-i-demo a15dc16 Revert "Create documentation"
...
Only displays unmerged branches
$ git branch --no-merged
rebase-i-demo
Only displays merged branches
$ git branch --merged
* master
untracked-demo
easier to understand
easier to review
easier to revert
$ git status ... Untracked files: ... README.md vendor/
$ git status -u $ // git config --global status.showUntrackedFiles all $ // git status ... Untracked files: ... README.md vendor/autoload.php vendor/composer/ClassLoader.php vendor/composer/LICENSE
$ git diff
$ git diff --staged
$ git diff -w
$ git add . $ // git add --all
$ git status
...
Changes to be committed:
...
new file: README.md
new file: composer.json
...
$ git add README.md
$ git status ... Changes to be committed: ... new file: README.md
Because you want atomic commits and not catch-all commits
$ git add -p README.md
... # Git (for beginners)
+ This repository is dedicated to the git workshop ... Stage this hunk [y,n,q,a,d,/,s,e,?]? y
...
## Commits ## Pushes
+## Branches ... Stage this hunk [y,n,q,a,d,/,s,e,?]? n
$ git reset README.md Unstaged changes after reset M README.md
$ git reset Unstaged changes after reset M README.md
$ git reset -p README.md ... ## Pushes +## Branches ... Unstage this hunk [y,n,q,a,d,/,s,e,?]?
$ git stash save "Fix a typo" $ //git stash save -u "Fix a typo" (also stash untracked files) Unstaged changes after reset M README.md $ git stash list stash@{0}: On master: Fix a typo
stash@{1}: On my-branch: Add italian translations
stash@{2}: On master: Fix bug #123
$ git stash show [stash@{0}]
README.md | 5 +++--
$ git stash apply stash@{1} ... Changes not staged for commit: modified: README.md
...
$ git stash pop stash@{1} ... Changes not staged for commit: modified: README.md
...
There is a shortcut for that
$ git stash -u Saved working directory and index state WIP on branch-name: 8ad48aa My commit comment HEAD is now at 8ad48aa My commit comment
$ git clean
$ git clean -d
$ git clean -n // equivalent to --dry-run
$ git clean -f
$ git commit -m "An intelligible message" README.md
[master 12345] An intelligible message
1 file changed, 1 insertion(+), 1 deletion(-)
$ git add CHANGELOG-1.0.md $ git commit --amend --no-edit
[master 67890] An intelligible message
2 files changed, 2 insertion(+), 1 deletion(-)
$ git commit --amend -m "A new message without typos"
$ git reset HEAD~1
// 1 is the number of commit to cancel
Unstaged changes after reset: M my-updated-file.md
(but do not revert the changes)
Push the current branch if it's tracked and distant and local name are identicall (default mode since git 2.0)
Push the current branch if it's tracked (regardless of its name)
$ git config --global push.default simple
$ git config --global push.default upstream
Warning: before git 2.0 default mode was matching. Push all branches having the same distant and local name
(tracked) $ git push -u origin tracked ... To git@github.com:antfroger/git-intro. * [new branch] tracked -> tracked Branch tracked set up to track remote branch to tracked origin
(untracked) $ git branch --set-upstream-to=origin/untracked untracked
Branch untracked set up to track remote branch to untracked origin
(BUG-123) $ git rebase -i origin/BUG-123
Before pushing, clean the history: remove useless commit, merge two commits, reorganise commits...
pick 6e70bd9 Add description pick 1b6d5ae Add dependency pick d590486 Forget dependency pick 08e6ace Fix typo pick af15bf3 Add changelog + create .gitignore pick f1f53a9 Create documentation pick a15dc16 Revert "Create documentation" ... # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = se commit, but stop for amending ...
By default, when you pull, git execute a merge after pulling.
But what you want is not merging the distant branch into your current branch but get the distant changes and re-execute your changes on the up-to-date local branch = rebase.
Merge should only be used to integrate your changes into a parent branch.
$ git config --global pull.rebase preserve
What's the difference ?
Git merge
Join two or more development histories together
A git merge should only be used for incorporating the entire feature set of branch into another one, in order to preserve a useful, semantically correct history graph. Such a clean graph has significant added value.
Christophe Porteneuve
Git rebase
Reapply commits on top of another base tip
Initial situation
Merge
Rebase
$ git log
Logs are useful to understand what was done.
Options are available
$ git log --stat
$ git log --graph
And many others...
$ git log -p $ git log -s
$ git log -U
$ git log --raw
$ git log --histogram
$ git log --shortstat
$ git log --summary
$ git log -z
$ git log --name-only
$ git log --check
...
La doc de git log: git-scm.com/docs/git-log
You want to search only on the tracked files ?
git grep is for you
$ git grep -a "doc" composer.lock: "doctrine/couchdb": "~1.0@dev", composer.lock: "doctrine/dbal": "~2.2", composer.lock: "doctrine/annotations": "~1.0", composer.lock: "doctrine/common": "~2.2", ... (END)
You want to search only on the tracked files ?
git grep is for you
$ git grep -a "doc" composer.lock: "doctrine/couchdb": "~1.0@dev", composer.lock: "doctrine/dbal": "~2.2", composer.lock: "doctrine/annotations": "~1.0", composer.lock: "doctrine/common": "~2.2", ... (END)
for listening to me