0

I am currently working on a commit

I have some modified files and also untracked files

I want to keep a backup of the current state for future reference.

I have read and found mainly using stash.

I want whatever files at the current stage should all be saved to the stash. (including untracked and also not to delete gitignore files)

I found git stash is being used. It will save the current state to stash and will have a clean working tree after stashing

Which of the following way to use git stash.

$ git stash save "my_stash" 

$ git git stash --include-untracked save "my_stash"

$ git stash --all save "my_stash"

then we get back the stash again using

$ git apply

Also if possible i want to know how to do the same thing by creating a branch instead of stash.

isherwood
  • 58,414
  • 16
  • 114
  • 157
Santhosh
  • 9,965
  • 20
  • 103
  • 243
  • [This question](https://stackoverflow.com/questions/835501/how-do-you-stash-an-untracked-file) would seem to cover the first part of your question. As to the second part, you may checkout a new branch, add the desired files, and commit. – Tim Biegeleisen Sep 23 '19 at 15:43
  • In the answer https://stackoverflow.com/a/835561/2897115 , it mentions two command `git stash --include-untracked` and `git stash -all` so which one to use – Santhosh Sep 23 '19 at 15:46
  • how about just `cp -r` for the whole repo? – Serge Sep 23 '19 at 15:47
  • I want to keep it as a reference. will git push also carry my stashes so that tomorrow when i git clone i can see all the stashed – Santhosh Sep 23 '19 at 15:50
  • @SanthoshYedidi "tomorrow when i git clone" - why are you making a new copy of the repo every day? You should only be cloning once and then updating as needed with fetch and pull. However, you may be overthinking this. Why not just make a branch? – Vlad274 Sep 23 '19 at 15:54
  • how to create a branch and see the same working dir and staging index and with the same recent commit to it – Santhosh Sep 23 '19 at 16:02

3 Answers3

0

Be aware that when you say "at the current stage", that implies something you clearly don't mean. (staged means 'in the index' in git-speak; that would definitely not include untracked files - nor unstaged changes to tracked files.)

As for what command to use, you should not use git stash save; it is deprecated, so you should use git stash push instead. (push is the default, so you don't have to name any subcommand at all when creating a stash.)

I'm not sure what you mean about how you want ignored files to be handled. If you want ignored files included in the stash

git stash --all

if you don't want the ignored files in the stash (and so want them to remain in the worktree)

git stash -u

And when you apply the stash, you need to let git know that you want the index restored

git stash apply --index

Note that this only works when the stash apply process doesn't generate conflicts; for this use, it shouldn't conflict, but if you apply to a different commit than from where the stash was created, it can.

To create a branch instead of a stash:

There's a shortcut you can use here, because a stash is really a collection of commits with a specially-handled ref. So you can create the stash as usual, then

git checkout stash
git checkout -b my_branch
git stash drop

The branch will look a little weird, because stash uses merges in a somewhat unusual way to assemble the untracked, unstaged, and staged change sets.

If you don't want to use the stash command at all, then it's harder. You can only commit changes that are staged, so you'd have to do something like

git checkout -b my_branch
git commit -m "staged changes"
git commit -a -m "unstaged changes"
# if you want a commit with only the non-ignored
# untracked files
git add :/:
git commit -m "untracked files'
# if you want a single commit with all untracked
# files (ignored or not), then skip the previous
# command and run this; if you want a separate 
# commit for ignored files, run the previous
# command and *then* run this:
git add -f :/:
git commit -m "ignored files"

(Note that you could even combine the unstaged, untracked, and ignored files all into one commit (though stash does not); but you really have to commit the staged changes separately, in order to restore the index accurately later.)

Then you need to restore your working state and continue work. The exact commands to use depend on which of the above commands you ran. First you want to detach from your stash-like barnch

git checkout --detach

Then restore the index with the staged changes. If you created all 4 commits, this would be

git reset --mixed HEAD~3

If you only created one commit for untracked files

git reset --mixed HEAD~2

(Or, if you only created one commit for unstaged changes and untracked/ignored files, it would be

git reset --mixed HEAD~1

or equivalent.)

Then move HEAD the rest of the way off the branch

git reset --soft HEAD~1

Finally check out your working branch again; e.g. if you started on master

git checkout master

With all of that done, you've stored all the same information as a stash; but you still don't have the automation of the stash command to help you, so in the future if you want to restore that state again, you would have to clean the work tree, check out the stash-like branch, and repeat the whole detach/reset/checkout procedure again.

And if you want to apply those changes to a different base commit (stock functionality for stash) you'd have to first rebase the stash-like branch to the new commit, and then restore the changes there.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
0

Mark's answer is fine so I'll just add this:

If you find yourself in this position often, wanting to essentially check out multiple branches simultaneously to compare changes and work on different changes, then you may want to use work trees. They make it easy to check out multiple branches without the overhead of multiple local repos (which can get very expensive on disk). You can also use a work tree to switch to another branch temporarily, do some work, and then come back without needing to create temporary branches or remember that you stashed some changes.

JDB
  • 25,172
  • 5
  • 72
  • 123
0

This is what i was looking for

I am currently on the masters branch, I am in between a work with some unstaged files and also with some untracked files. I want to save my current state into a new branch just as a backup/reference for future.

So i did stash push --include-untracked in my current state and then create and checkout to a new branch and stash apply there and stage all files by add -A and then commit changes. Again come back to master branch and again do stash apply there.

there

$ git status

On branch master

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   filename1

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    filename2

no changes added to commit (use "git add" and/or "git commit -a")

$ git stash push --include-untracked

One stash is run

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

$ git checkout -b backup_branch
Switched to a new branch 'backup_branch'

$ git stash apply
On branch backup_branch


Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   filename1

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    filename2


$ git status
On branch backup_branch


Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   filename1

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    filename2

$ git add -A

$ git commit -m "Saved for backup"

$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

$ git stash apply
On branch origin/master


Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   filename1

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    filename2

$ git status
On branch origin/master


Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   filename1

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    filename2

Now i am back with the same working dir. With a backup of my current state in a new branch backup_branch

Santhosh
  • 9,965
  • 20
  • 103
  • 243