In basics, we will be covering config, init, add, rm, .gitignore, commit, log, blame, diff, tag, describe, show and stash
This picture, sort of gives an overview, where each of the commands we will be covering, fit in the git world.
Commands | Description |
---|---|
git help | Open local documentation on specific topic |
git config | Setting up configuration parameters, metadata that will be used during object creation |
git init | Initializes the repository |
git add | Adds file to the staging area |
git rm --cached | Unstage & Untracks the file |
git rm | Delete file from working directory & stages the deletion |
git mv | Rename a file eg:- git mv Index.txt Index.html |
.gitignore | Files/Folders mentioned in this file will be ignored |
git status | View status of files in working directory & staging |
git commit | Takes snapshot of the staging area |
git log | Show commits made in the repository in reverse chronological order. (ie., latest at top ) |
git blame | Shows who was the last person to change code in a program |
git diff | Shows difference in files in working directory and staged |
git diff --cached | Shows difference in files in staged and repository |
git ls-files | Show information about files in the index and the working tree. Eg: git ls-files --stage |
git tag | It refers a commit point and gives it a human readable name |
git describe | Used with tags, gives an object, a human readable name based off of the nearest annotated tag |
git help -a
command shows all available git commands which you enter locally in your system.
git help everyday
: Opens your web browser having useful minimum set of commands for Everyday Gitgit help add
, opens your web browser with page related to git add
. There are 3 types of configuration, below shows the command and respective location where these settings are stored.
Commands | File locations |
---|---|
git config --local --list | cat .git/config |
git config --global --list | cat ~/.gitconfig |
git config --system --list | /etc/gitconfig |
To view the all the config settings including alias use git config --list
Git provides ability to setup name and email different for local(--local
) and global(--global
).
1git config --local user.name "sushanth"2git config --local user.email "bobby.dreamer@gmail.com"
1git config --global user.name "sushanth"2git config --global user.email "bobby.dreamer@gmail.com"
Use --unset option to remove a setting
git config --unset --global user.email
Changing default editors ( default is vim )
1git config --global core.editor ~/bin/vimgit2git config --global core.editor "nano"
git init
command will initialize current folder as a git repository. Basically it will create a new hidden folder called .git
which will contain all the git objects. This command also creates a default branch called master
(in future it could be called as main
). Another flavor of the command is git init folder-name
where it will create a new folder in initialize git in it.
In order to start tracking file changes, the file needs to be added to git. It can be done by executing command git add
and when its added you can say the file is staged and tracked. This phase is also known as 'adding files to INDEX'. Next phase that comes after git add
is git commit
, here all the staged files are committed(saved), they will be part of git repository history.
Below are multiple ways a file can be added to git
Commands | Description |
---|---|
git add fileA.txt | Add file fileA.txt to staging area |
git add fileB.txt fileC.txt | Adding multiple files to staging area |
git add . | Add all files & subdirectories with files to staging area |
git add f* | Add all files starting with f* to staging area |
git add -f . | Add all ignored files. Long command --force |
Git uses a heuristic to try to determine if a file is a binary or not. If you don't trust automatic detection and want to state is explicitly, you can do by creating a .gitattributes
file like below.
1*.pbxproj binary2*.pickle binary3*.exe binary4*.foo -crlf -diff -merge
Now, Git won’t try to convert or fix CRLF issues; nor will it try to compute or print a diff for changes in this file when you run git show or git diff on your project.
This is one of the most used commands and it has few flavours.
git status
: default (shows changes to be committed and Untracked)
1$ git status2On branch name23Changes to be committed:4 (use "git reset HEAD <file>..." to unstage)5
6 deleted: b.txt7
8Untracked files:9 (use "git add <file>..." to include in what will be committed)10
11 .gitignore
git status --ignored
: This will additionally show the ignored files as well.
1$ git status --ignored2On branch name23Changes to be committed:4 (use "git reset HEAD <file>..." to unstage)5
6 deleted: b.txt7
8Untracked files:9 (use "git add <file>..." to include in what will be committed)10
11 .gitignore12
13Ignored files:14 (use "git add -f <file>..." to include in what will be committed)15
16 b.txt17 c.txt
git status -s
: Short format of the output. Default is the long format.
1$ git status -s --ignored2A d.txt3?? .gitignore4?? e.txt5!! b.txt6!! c.txt
Meaning of symbols A
:Added, D
:Deleted, ??
:Untracked, !!
:Ignored
This is a file where we can mention what files/folders to be ignored while tracking changes.
Possible files that we can ignore are
Whats are recommended to add it .gitignore
1node_modules2npm-debug.log*3.DS_Store
Note : When you are building a big app, let just say enterprise level, dont ignore node_modules
because all the npm modules are mostly open source written by a third-party who might not support later, so there is this possibility of packages getting disappeared later. For instance take kik, left-pad, and npm.
pattern | Description |
---|---|
**/logs | You can prepend a pattern with a double asterisk to match directories anywhere in the repository. |
**/logs/debug.log | You can also use a double asterisk to match files based on their name and the name of their parent directory. |
*.log | An asterisk is a wildcard that matches zero or more characters. |
*.log !important.log | Prepending an exclamation mark to a pattern negates it. If a file matches a pattern, but also matches a negating pattern defined later in the file, it will not be ignored. |
/debug.log | Prepending a slash matches files only in the repository root. |
debug.log | By default, patterns match files in any directory |
debug?.log | A question mark matches exactly one character |
debug[0-9].log | Square brackets can also be used to match a single character from a specified range. For alphabetic [a-z] |
debug[!01].log | An exclamation mark can be used to match any character except one from the specified set. |
logs | If you don't append a slash, the pattern will match both files and the contents of directories with that name. In the example matches on the left, both directories and files named logs are ignored |
logs/ | Appending a slash indicates the pattern is a directory. The entire contents of any directory in the repository matching that name – including all of its files and subdirectories – will be ignored |
logs/**/debug.log | A double asterisk matches zero or more directories. |
logs/debug.log | Patterns specifying a file in a particular directory are relative to the repository root. (You can prepend a slash if you like, but it doesn't do anything special.) |
There are multiple ways to check to see if the files are ignored.
git check-ignore
git status -s --ignored
git status
section abovegit ls-files --others --ignored --exclude-standard
--others
: Shows untracked files --ignored
: Shows only ignored files --exclude-standard
: Add the standard Git exclusions: .git/info/exclude
, .gitignore
in each directory, and the user's global exclusion fileIn the below scenario, there are 5 files at different stages(committed, staged, working directory and ignored). Review the command outputs.
1$ ls -l2total 53-rw-r--r-- 1 Sushanth 197121 4 Oct 16 22:19 a.txt # Committed4-rw-r--r-- 1 Sushanth 197121 2 Oct 18 15:12 b.txt # Ignored 5-rw-r--r-- 1 Sushanth 197121 2 Oct 18 15:12 c.txt # Ignored 6-rw-r--r-- 1 Sushanth 197121 2 Oct 18 16:16 d.txt # Staged7-rw-r--r-- 1 Sushanth 197121 2 Oct 18 16:17 e.txt # Untracked8
9$ cat .gitignore10b.txt11c.txt
There are multiple flavours ( i prefer flavour 2 )
1# Flavour 1 : Plain, just shows the ignored files2$ git check-ignore *3b.txt4c.txt5
6# Flavour 2 : Shows ignored files with the rule used to ignore it (-v:verbose)7$ git check-ignore -v *8.gitignore:1:b.txt b.txt9.gitignore:2:c.txt c.txt10
11# Flavour 3 : Shows matched & unmatched files (-n:non-matching)12$ git check-ignore -vn *13:: a.txt14.gitignore:1:b.txt b.txt15.gitignore:2:c.txt c.txt16:: d.txt17:: e.txt
node_modules
but ignore the rest Below is the easiest way to ignore node_modules
folder
1node_modules/
In my case i want to track changes in folder node_modules/@lekoarts/
. So as per the gitignore documentation, when negating.
it is not possible to re-include a file if a parent directory of that file is excluded.
In other words, no greedy matches, you cannot use **
. Below you can see that node_modules/@lekoarts
folder is getting ignored due to node_modules/
mentioned in .gitignore
file line number 36.
1node_modules/2
3# output4> git check-ignore -vn node_modules/@lekoarts 5.gitignore:36:node_modules/ node_modules/@lekoarts
Below i have included !node_modules/@lekoarts
with excalmation symbol, a negating pattern to un-ignore the file/folder. But git check-ignore
shows same output.
1node_modules/2!node_modules/@lekoarts3
4# output5> git check-ignore -vn node_modules/@lekoarts6.gitignore:36:node_modules/ node_modules/@lekoarts
When you introduce a *
single-level wildcard. It works. Now it shows the line number 37 in .gitignore
using negating pattern and using git status
we can confirm that folder will be added as before when executing git status
, node_modules/
folder wouldn't appear.
1node_modules/*2!node_modules/@lekoarts3
4# output5> git check-ignore -vn node_modules/@lekoarts6.gitignore:37:!node_modules/@lekoarts node_modules/@lekoarts
This command will remove file from both the staging and the working directory.
git rm fileF2.txt
Option flags available are -f
:force, -n
:dry run, -r
:recursive
Eg:- git rm -rf fileF1.txt
will recursively & forcibly delete file from Working directory & Repository
Note : If a file is deleted using git rm
and that change is committed. To recover the file, use git reflog
to find a ref that is before the git rm
execution.
git rm --cached fileF1.txt
--cached
is used to unstage and remove paths from the index. Scenario where this command could be useful is,
Scenario 1 : Unstaging everything git rm -rf --cached .
Scenario 2 : Suppose you create .gitignore after files have been staged or committed. Now to unstage and those specific files you can use the below method.
1git rm -rf --cached `git ls-files -i -X .gitignore`
Note 1 : in the above command, its not single quotation but tilde symbol.
-rf
: recursively and forcefullygit ls-files
: Show information about files in the index and the working tree-i
: Show only ignored files in the output-X
: Read exclude patterns from (file); 1 per lineNote 2 : You have a problem, if that was a confidential file, even so it was removed by above method. Since you added it, it will be somewhere inside as a git object. You have to hunt that down and delete it.
I
and start typing the comments and then [ESC] :wq
to save and exitgit commit -m "October 2020 - Git Theory post"
Some standard procedures one need to set when writing commit messages. It should easily help one understand about that commit.
<ACTION> : <WHEN> : Description(50 chars max)
Add : October 2020 : Added a new post
Committing specific files
git commit -m "Add : August 2020 : Adding second.txt" second.txt
Staging & Committing tracked files in a single command
git commit -a -m "Update : Dec 2019 : Emergency commits"
Amending commit
git commit --amend -m "New commit message"
1git add forgottenfile.txt2git commit --amend --no-edit
--no-edit
means Comment does not changeDummy commit
git commit --allow-empty -m ‘Initial branch empty commit’
Shows the commit logs ( latest at top ) and each commit contains following information
git log –p
git log --all --decorate --oneline --graph
git log
but provides all basic info. git log --graph --format=%s
git log -n 3
git log --since=5.days --author=Sushanth
git lol d9e798a..804e1db
git log v1.0..v2.0
git lol --grep="Add"
git lol -- f7.txt
git log --full-history -1 -- f1.txt
-1
to show just last commit, can be increased. It recommended to use alias to shorten long git log commands
git graph
git config --global alias.graph "log --all --decorate --oneline --graph"
git lofi
git log --oneline --name-status --graph
git config --global alias.lofi "log --oneline --name-status --graph"
git lol
git log --graph --pretty=format:'%C(yellow)%h%Creset -%C(cyan)%d%Creset %s %Cgreen(%cr) %C(magenta)<%an>%Creset' --date=relative
git config --global alias.lol "log --graph --pretty=format:'%C(yellow)%h%Creset -%C(cyan)%d%Creset %s %Cgreen(%cr) %C(magenta)<%an>%Creset' --date=relative"
Referencing commits from HEAD using ~ and ^
This command summarizes the git log output. It groups all commits by author and includes the first line of the commit message. That (23)
is the total commit, i had done in the test.
1$ git shortlog2Sushanth Bobby Lloyds (23):3 initial commit4 Adding F3.txt5 Updated f1.txt6...7
8# -s:Suppresses the commit message and provides count, -n:sorts output based on commit count9$ git shortlog -sn10 23 Sushanth Bobby Lloyds
As the name tells, it will tell you who changed the file last. Below i am just trying to see who added the file g.txt
1$ git ls-files -s2100644 7a8e17364db020c34670f00f6e7473a6d457cf5b 0 a.txt3100644 00479302f1a096d1fa5fd53abb2bcf79908b1d16 0 b.txt4100644 6ad93728a01d93effb3b6a2c8b12bc8ea999bc57 0 c.txt5100644 d102f3fd7e19939ec42cf015ade11a5f96aaf997 0 d.txt6100644 dfd49bc24fa0ae3c4ec1d121e45fc55078394f63 0 e.txt7100644 f1d86f4b27f1990368072562534c43e2b981c4db 0 f.txt8100644 a2e4e883b5423c8d35301828fc96bb2d480f790c 0 f1.txt9100644 0ac8e950b1dfcfba626ad613bf935b678892239b 0 f2.txt10100644 7b855c80b44dcdb1bec0f75f8721da8b93279884 0 f3.txt11100644 941901aa8eae68b75cf6265c27edfa55ad501766 0 f4.txt12100644 b33f2940f9f546b1bec4aa03a4bc056f22c7af00 0 f6.txt13100644 e9678181fd88b69443cb24ebe9f5e552c6a986f3 0 f7.txt14100644 d028b559cc081dd915679d4fc395be259870ce0f 0 g.txt15
16$ git blame g.txt1783ce55e7 (Sushanth Bobby Lloyds 2018-12-04 11:11:18 +0530 1) initial g
Above commit objects are C1
:Contains(f1.txt, f2.txt), C2
:f3.txt, C3
:Updated f1.txt
git diff
compares files in working directory & staging area/INDEXgit diff –cached
compares files in staging area & last commit. Also --staged
is a synonym for cached.Setup
1echo "F1" >> F1.txt2echo "F2" >> F2.txt3git add . 4git commit -m "Add : F1.txt, F2.txt"5echo "F3" >> F3.txt6git add . 7git commit -m "Add : F3.txt"8echo "F1 : Feature 1" >> F1.txt9git add .10echo "F1 : Feature 1 - New Changes" >> F1.txt11
12$ git status13On branch master14Changes to be committed:15 (use "git reset HEAD <file>..." to unstage)16
17 modified: F1.txt18
19Changes not staged for commit:20 (use "git add <file>..." to update what will be committed)21 (use "git checkout -- <file>..." to discard changes in working directory)22
23 modified: F1.txt
1$ git diff F1.txt2warning: LF will be replaced by CRLF in F1.txt.3The file will have its original line endings in your working directory.4diff --git a/F1.txt b/F1.txt5index 6b30d17..c08ef58 1006446--- a/F1.txt7+++ b/F1.txt8@@ -1,2 +1,3 @@9 F110 F1 : Feature 111+F1 : Feature 1 - New Changes
1$ git diff --cached F1.txt2diff --git a/F1.txt b/F1.txt3index 66d43ba..6b30d17 1006444--- a/F1.txt5+++ b/F1.txt6@@ -1 +1,2 @@7 F18+F1 : Feature 1
Committing changes that were staged
1$ git commit -m 'Update : F1.txt : Feature'2[master 1c2875b] Update : F1.txt : Feature3 1 file changed, 1 insertion(+)
git diff <old-hash> <new-hash>
If you think, its hard to remember those hashes, then you need to tag them, thats the next subject git tags
Tag is used to mark a particular commit point as a milestone, a new stable release or a new version.
Why use tag ?
There are two types of tags
This is a simple tag which just stores hash of the commit they refer to.
git tag <tagname>
Example : git tag v1.0
Example : git tag v1.0 <hash>
This type of tag stores extra meta data information like
git tag –a <tagname>
git tag –a v2.0
git describe
is only applicable for “annotated tag”. Continuing above example, made some changes to all the three files and performed a commit.
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/diff (master)2$ git commit -m "Updated all 3 files"3[master 3d4728e] Updated all 3 files4 3 files changed, 3 insertions(+), 2 deletions(-)5
6Sushanth@Sushanth-VAIO MINGW64 /d/GITs/diff (master)7$ git lol8* 3d4728e - (HEAD -> master) Updated all 3 files (3 seconds ago) <Sushanth Bobby Lloyds>9* 1c2875b - (tag: v2.0) Update : F1.txt : Feature (24 hours ago) <Sushanth Bobby Lloyds>10* efd122b - Add : F3.txt (24 hours ago) <Sushanth Bobby Lloyds>11* a891bb1 - (tag: v1.0) Add : F1.txt, F2.txt (24 hours ago) <Sushanth Bobby Lloyds>12
13Sushanth@Sushanth-VAIO MINGW64 /d/GITs/diff (master)14$ git describe15v2.0-1-g3d4728e
In the above example,
Commands | Description |
---|---|
git show tagname | shows details of object |
git tag | Lists all tags |
git tag –n | List all tags with their messages (tag message or commit message if tag has no message) |
git tag –l –n3 | Lists tags with messages (max 3 lines) |
git tag –d tagname | Delete a tag |
git tag –a –f tagname (commit-id) | To replace existing annotated tag |
git checkout tagname | To view files of that specific version (detached HEAD state) |
git push (location) tagname | A tag is just a reference to your local repository and it is not automatically pushed to the remote repository with the rest of the code. |
git push (location) --tags | Push all tags at once |
git tag tagname -m 'message' (commit-id) | create tags for a certain commit-id |
Shows details of objects like blobs, trees, tags and commits and output differs based on object types.
git diff-tree --cc
.git ls-tree with --name-only
).Continuing with above Tag example, v1.0 is a light-weight tag and v2.0 is a annotated tag. Below, i can use v1.0
instead of a891bb1
, there wouldn't be any difference in the output.
Showing annotated tag v2.0,
git show v1.0^{tree}
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/diff (master)2$ git show v1.0^{tree}3tree v1.0^{tree}4
5F1.txt6F2.txt7
8Sushanth@Sushanth-VAIO MINGW64 /d/GITs/diff (master)9$ git show v2.0^{tree}10tree v2.0^{tree}11
12F1.txt13F2.txt14F3.txt
Syntax : git show [reference]:[file_path]
[reference]
: can be a branch, tag, HEAD or commit IDWe are going test file f7.txt
1$ git lol -- f7.txt2* 25dc023 - (tag: v2.0) Revert "f7.txt Update 1" (1 year, 11 months ago) <Sushanth Bobby Lloyds>3* d9e798a - f7.txt Update 2 (1 year, 11 months ago) <Sushanth Bobby Lloyds>4* 2f161e1 - f7.txt Update 1 (1 year, 11 months ago) <Sushanth Bobby Lloyds>5* 431be32 - f7.txt Initial (1 year, 11 months ago) <Sushanth Bobby Lloyds>
When the file was added initially, it looked like this
1$ git show 431be32:f7.txt2One3Two4Three5Four
currently it looks like this
1$ git show master:f7.txt2One3Two4Three54
git show head:F1.txt
: Shows content of file from HEAD(latest commit)git show :F1.txt
: Shows content of file from staging And you can make a copy of the file by doing git show 431be32:f7.txt > old_f7.txt
git stash
will stashIt takes the changes of TRACKED modified files in your working directory and staging area and saves it in a stack and later when you require them you can reapply.
Following are the basic stash commands :
commands | Description |
---|---|
git stash | Add changed content to stash |
git stash list | List items in stash |
git stash show -p stash@{n} | View the content of stash with difference |
git stash apply | Applies the latest stash to the current working branch and copy will remain in the stash |
git stash pop | Applies the latest stash to the current working branch and removes the stash entry |
git stash clear | Clears the stash |
git stash push –m "Added on dd/mm/yyyy" | Adding user-defined message to stash |
Name | Description |
---|---|
stash@{0} | Its a stack, so latest one stashed will be at top having index as 0. In the pic you can see, top one has user provided comment. |
stash@{1} | It’s the stash that was created before stash@{0} and it has the default comment |
There are multiple ways to apply stash.
Command | Description |
---|---|
git stash apply | Simplest. Applies the recent stash (i.e., stash@{0}). Unstages the old files if it was staged. |
git stash apply stash@{1} | To apply specific stash |
git stash apply 0 | Stack number can be also used directly. |
git stash apply 0 --index | This will stage the files which were staged before |
git stash pop | Simplest. Applies the recent stash |
git stash pop 1 | To apply specific stash |
Two ways to remove items from stash i)drop ii)clear
Command | Description |
---|---|
git stash drop 0 | Drops item stash@{0} from stash stack |
git stash clear | Empties the stash |
Git will include untracked files in the stash being created.
1git stash push -u2git stash push -u -m "This stash includes untracked files too"3git stash --include-untracked
git stash --all
Below picture says it all.
git stash branch <new branchname>
git checkout -b my-new-branch
+ git stash apply
+ git stash drop
1$ git stash2$ git checkout branch23$ git stash pop
Test Plan
Run all the commands in the setup and below should be the current state of the setup.
1mkdir stashtest2cd stashtest3git init4echo "First Commit" > comitted-file.txt5git add comitted-file.txt6git commit -m "Initial Commit"7echo "Staging file" >> comitted-file.txt8git add comitted-file.txt9
10echo "This is to be staged" > a.txt11echo "This should be in working directory" > b.txt12
13echo "This file is ignored" > ignored-file.txt14echo "ignored-file.txt" > .gitignore15echo ".gitignore" >> .gitignore16
17git add a.txt
git stash
only stashes files comitted-file.txt and a.txt. It doesnt stash b.txt as it is not tracked.
git stash show
shows files in the latest stash. If there were multiple stashes git stash show stash@{1}
shows file in the earlier stash. Note : index 0 points to the latest and 1 earlier than 0.
git stash show -p
compares and shows differences. In our scenario,
git stash apply
or git stash apply 0
applies the latest stash and following occurs,
git stash push -u -m "Stashing Tracked & Untracked files"
using this command we can stash tracked & untracked files.
git stash show
shows tracked files but there is no easy way to see or list untracked files.
git rev-list -g stash | git rev-list --stdin --max-parents=0 | xargs git show --stat
this command lets you see the untracked file.
git show stash@{0}^3
this command shows Untracked files. Basically untracked files are stored in the third parent of a stash commit. (This is not documented)
git stash push -a -m "Stashing all files including ignored"
using this command we can stash all (tracked, untracked & ignored)files.
When you do git stash show
there wouldn't be any output, if you have stashed only ignored files.
git show stash@{0}^3
shows ignored files as well. git stash pop
or git stash pop 0
will pop the latest stash to working directory and remove item from stash list
git stash drop 1
using command item at index 1 is dropped.
git stash clear
clears the stash.
After the executing all the git stash setup commands for test, this is the current state of git repository and directory.
Sequence of images are left to right,
After applying the stash you can notice,
On left, you can notice, new file a.txt is staged and comitted-file.txt which was staged before stashing got unstaged and b.txt is in same state as it was never tracked or added to git.
On right, you can see the files which had disappeared after stash are now available.
Untracked file here is b.txt and even after executing the command you can notice b.txt doesn't show up on stash show because gits like that.
On the right, you can see the command used to view the untracked file.
Untracked files are stored in the third parent of a stash commit.
Again as before all untracked & ignored files are stored in the third parent of a stash commit.
Git creates two commits(by default) when you run the command git stash
. The special ref at .git/refs/stash
points to your most recently created stash and previously created stashes are referenced by the stash ref's reflog. This is why you refer to stashes by stash@{n}: you're actually referring to the nth reflog entry for the stash ref. Since a stash is just a commit, you can inspect it with git log
In the output below HEAD is at 260b361
.
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/git (master)2$ git lol -53* 260b361 - (HEAD -> master) Deleting a c d e text files (1 year, 10 months ago) <Sushanth Bobby Lloyds>4* 25bde47 - (tag: V4, stash/start) Updated readme.txt & adding back c d e (1 year, 10 months ago) <Sushanth Bobby Lloyds>5* d4bff73 - (tag: V3) Merge reset/finished into master (1 year, 10 months ago) <Sushanth Bobby Lloyds>6|\7| * 1ab856b - (reset/finished) Adding a.txt (1 year, 10 months ago) <Sushanth Bobby Lloyds>8|/9* b77ca73 - (reset/start) Updated readme.txt for RESET (1 year, 10 months ago) <Sushanth Bobby Lloyds>
In the below output, still the HEAD is at 260b361
but there are two commits above it and have a look at the messages and it will reveal it was created stash.
commit 458a388b0fcb94579cd68404c2edae718d37d509 (refs/stash)
: WIP on master: 260b361 Deleting a c d e text filescommit 86055785f42ce7866f824146e1f441e5ece958e0
: index on master: 260b361 Deleting a c d e text files1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/git (master)2$ git log --graph --all refs/stash -33* commit 458a388b0fcb94579cd68404c2edae718d37d509 (refs/stash)4|\ Merge: 260b361 86055785| | Author: Sushanth Bobby Lloyds <bobby.dreamer@gmail.com>6| | Date: Thu Oct 15 22:01:21 2020 +05307| |8| | WIP on master: 260b361 Deleting a c d e text files9| |10| * commit 86055785f42ce7866f824146e1f441e5ece958e011|/ Author: Sushanth Bobby Lloyds <bobby.dreamer@gmail.com>12| Date: Thu Oct 15 22:01:21 2020 +053013|14| index on master: 260b361 Deleting a c d e text files15|16* commit 260b3619e6447bc1ef6f33746e879286490e8ba8 (HEAD -> master)17| Author: Sushanth Bobby Lloyds <bobby.dreamer@gmail.com>18| Date: Mon Dec 10 22:56:29 2018 +053019|20| Deleting a c d e text files
Below is the simplest diagram for above approach,
1# H:HEAD, I:Index, W:Working directory 2 .----W3 / /4-----H----I
If you include git stash --all
, you will get 3 commits as in this case git will stash untracked files as well.
1# H:HEAD, I:Index, W:Working directory, U:Untracked files2 .----W----.3 / / /4-----H----I U
When you run git stash pop
, the changes from the commits are used to update your working copy and index, and the stash reflog is shuffled to remove the popped commit. Note that the popped commits aren't immediately deleted, but do become candidates for future garbage collection.
1# if you know the hash of the stash commit you dropped, you can apply it as a stash2git stash apply $stash_hash3# or create a separate branch for it4git branch recovered $stash_hash
1git stash save --keep-index --include-untracked2# then afterwards3git stash drop
git rm
or git reset
they will be in there dangling. Its not easy to find them.1git checkout -- .2git reset --hard3git clean -f