Our team works on repository which includes one directory where there are files with pipe character "|". I'm the only one on Windows so pipe character is illegal for files names.
Is there a way to rename files in the directory "extra" from ex. "2021|08|05" to "2021\08\05" when I make "git pull"?
Is there a way to rename files in the directory "extra" from ex. "2021\08\05" to "2021|08|05" when I make "git push"?
No.
No.
These are the right answers to the question you've asked, but the trick is, you've asked the wrong question. Alas, the answer to the right question is: "yes, but it's a horrible solution". The question is: Is there a solution to the problem of bad / invalid characters in file names stored in Git commits?
In the early days of Git, when it was a collection of shell scripts that only a few people could use successfully, 😀 one would obtain new commits from elsewhere with git fetch, then read these commits into Git's index with git read-tree.
Git's index, which Git also calls the staging area or sometimes the cache, can hold these file names. In fact, even on Windows, Git's index can hold files named aux.h, which Windows won't let you create. The index has no folders either: it just has files with names with embedded (forward) slashes, such as path/to/file. Git can hold two different files, one named README and one named readme, in its index. WIndows can't have two different files whose name only differs in case.
So, Git's index / staging-area can hold these files just fine. The problem comes when you go to work with the files. Files that are in Git's index, are stored there in a special Git-only format, as what Git calls a blob object. You cannot read or write a blob object directly. You have to use yet more Git commands to do this. It's terribly inconvenient.
To use Git conveniently, then, we normally don't use all the individual one-step-at-a-time internal Git operations: we use some sort of higher level, user oriented command, like git checkout. We check out an entire commit: Git will find all the files that are stored in that commit, read them into Git's index, and copy out and expand all the internal Git-only blob objects into ordinary files, with ordinary file names.
This step—copying files out of Git's index, to make them usable—is where things go wrong, on Windows. The file's name in Git's index is, say, path/to/2021|08|05. Git recognizes that path/to/ has to be turned into two folders, path\ and path\to\, on Windows, so that Git can create a a file in the second folder. Unfortunately, Git has no way to remap the 2021|08|05 part. That part is going to stay 2021|08|05, and as you have seen, Git can't create a file with that name: the OS just says "no".
What you can do, at this point, is drop down to those lower-level commands. You can run:
git rev-parse :path/to/2021|08|05
perhaps with quotes if needed, depending on your shell:
git rev-parse ":path/to/2021|08|05"
This git rev-parse command will show the blob hash ID for the file. You can then access the file's contents with:
git cat-file -p <hash>
which prints those contents to the standard output. If your shell supports redirection, you can then redirect the output to a file whose name is your choice. This lets you see and use the file's contents.
The git cat-file -p command can take the index path name directly, so:
git cat-file -p ":path/to/2021|08|05" > path/to/2021-08-05
is a way to extract the file to a usable name.
Unfortunately, git add—which is how you would normally update the file—will insist on using the name you gave the file in the file system. Once again, you must fall back on internal Git plumbing commands to work around this. If you need to update that particular file, for instance, you would:
run git hash-object -w -t blob path/to/2021-08-05 to turn the updated file's data into an internal Git object;
run git update-index with arguments to make Git update the entry for path/to/2021|08|05 using the hash ID obtained in step 1.
Once all of this is done, you can go back to normal Git commands, because git commit makes a new commit from what's in Git's index / staging-area.
The (rather large) drawback here is that you cannot use a lot of normal everyday Git commands:
git pull is often a no-go because it runs git rebase or git merge, both of which need to use your working tree (OS-level files). Run git fetch first, then do as much manual work as needed.
git checkout will fail: you can use it, but then you must manually do something about each of the bad file names that are now in Git's index.
git diff will show differences that include deleting the files with the bad names, and git status will show the adjusted-name files as untracked files (because they are).
git add of any changes you need to make to these files is also a no-go; use git hash-object -w and git update-index instead.
git rebase and git merge become difficult. You probably can deal with them as in steps 2 and 4, but that's painful at best.
I'm working on a project that's hosted on GitLab and uses issue/work branches and merge requests to bring that work into the master branch when it's done. Usually I work on issue branches. When it has been merged by GitLab, I need to switch to the current master to do a build, locally.
My workflow is this:
Switch to master
Pull from remote (--ff-only)
Remove stale remote tracking branches
Also remove their local tracking branches
There's also a client-side tool that watches the code directory and updates some files (CSS, JavaScript). When it sees a change in the first step (switch to master), I first need to wait for it to finish before going on (to avoid confusion). If there's a difference between the issue branch and the old master, there's a good chance that the difference will disappear when updating master (as that issue branch is now merged).
I'm looking for a way to switch to the already-updated master branch in one step. How can I do that with a git command? I want to bundle up all these actions in a batch file to avoid repeating all those manual steps in TortoiseGit every time.
This question is different from the suggested one in that the local master branch already exists. I'm not switching to a new branch from a remote, but to a branch that already exists and it just behind the remote.
TL;DR
Unless you write your own script (or use a Git alias to run multiple commands and/or scripts), you can't get this down to a single command, but you can get closer. See the long section for many caveats: the biggest one is that it assumes you're not already on master when you do it. If you are, the second step won't work (see the long section for what will).
git fetch -p &&
git fetch . refs/remotes/origin/master:refs/heads/master &&
git checkout master
will take care of the first three bullet points—not in the same order—with a single work-tree-updating git checkout step.
(Note that I split this into three lines for posting purposes, but as a Git alias using !, it's really all one big line.)
Long
There are several approaches, including actual, literal batch files (shell scripts on Unix-like systems, or .BAT files, or whatever) and aliases (as suggested by Joe in a comment).
There's also a client-side tool that watches the code directory and updates some files ...
This is ... not necessarily a good idea, let's say. :-)
While git checkout master runs, it's changing various files. Let's say that for some reason, it changes one of several files that the watcher watches, but then it pauses for a few minutes (or seconds, or microseconds, or some unit of time anyway). While it is paused, the watcher tries to combine the multiple files that are now out of sync.
Maybe this is OK and self-correcting when Git un-pauses and finishes the checkout—but it might be better if you could make sure the update only happens when the checkout is done.
That aside, let's take a look at this particular series of commands, and be very concrete about which Git command you're using:
Switch to master
I assume this is git checkout master.
Pull from remote (--ff-only)
I assume this is git pull origin master --ff-only or perhaps just git pull --ff-only.
Remove stale remote tracking branches
I'll assume for now that this is git fetch --prune. If you are doing something different, you should include that in your question.
Also remove their local tracking branches
If I understand what you mean, this requires a script. Note that this is somewhat dangerous: suppose you have your own branch X on which you are doing development. This X is not related to anyone else's X. Then someone creates their own X—using the same name—and sends it to the machine from which you git fetch. You now have origin/X. Then they delete their X (because they're done with it) and delete origin/X. If you now have your script delete your X, because origin/X went away, that would probably be bad.
If you only delete your X when it explicitly has origin/X set as its upstream, this particular case won't occur—but if someone accidentally deletes your origin/X thinking it was their origin/X, the same problem crops up again, and this time that particular protection does not work.
Anyway, with all that aside, let's look at the variant I suggested above.
git fetch -p
This updates all your origin/* names,1 including origin/master, without affecting any files in your working tree. The -p is short for --prune, so it deletes any origin/* names that no longer have a corresponding branch in the Git over at the URL stored under the name origin.
1I assume here that you have only one remote, which is named origin. If you have more than one remote, use git fetch origin -p to make sure you're fetching specifically from the one named origin. I also assume you have not configured your Git to be a single-branch clone.
git fetch . refs/remotes/origin/master:refs/heads/master
This rather magic-looking command tells your Git to call itself up. That is, the special name . refers to your own Git repository. We are using this to trick your Git into fast-forwarding your master branch based on your updated origin/master. The final argument is what does this: we say to your Git: OK, my Git, when you talk to that other Git, find out what commit its refs/remotes/origin/master identifies. Then, if that's a fast-forward operation, update my refs/heads/master to match.
Of course, the "other Git" your Git is talking to is itself—so this means fast-forward my master from my origin/master.2 It's roughly equivalent to:
git checkout master && git merge --ff-only origin/master && git checkout -
except that no actual checking-out occurs: no files in your work-tree change.
2You might wonder why some of these use origin/master and some use refs/remotes/origin/master. The longer one is just the full spelling of the name. When using git fetch, it's wise to use the full spellings. In fact, in general, in scripts, you might want to use full spellings more often, but specifically git fetch can become confused if the other Git you talk to accidentally has both a branch and a tag with the same name, for instance. So I'm illustrating the full names with git fetch. You'll use it to talk to your own Git, so if you don't mix up your tags and branch names or otherwise create ambiguity, you won't actually need the full names. But it's a good habit with git fetch.
The above fails if you're on your master
The git fetch command will refuse to fetch into whatever branch name you have checked out. So if you are on master, this git fetch . trick will fail.
In a way, this is OK! If you are on your master, what you should do instead is run:
git merge --ff-only origin/master
or anything equivalent. This is what your git pull --ff-only does: first it runs git fetch (without the -p and limited to fetching only the other Git's master); then it runs git merge --ff-only.
A more complete version
A more complete version of this sequence, then, is to first check: Which branch am I on? To do that, you can use either of two Git commands:
git rev-parse --abbrev-ref HEAD
or:
git symbolic-ref --short HEAD
Both of these will print master if you are currently on your own master branch. The difference between them is what they do if you're on no-branch-at-all: e.g., in the middle of a rebase, when you are in "detached HEAD" state. In that case, the second command—the git symbolic-ref one—errors out, while the first one just prints HEAD.
If you'd like to avoid doing any of this when in such a state, use the second command and check for failure. Otherwise, use the first one. I'll illustrate just the first one here:
if test $(git rev-parse --abbrev-rev HEAD) = master; then
# already on master - use alternative strategy
git fetch -p && git merge --ff-only refs/remotes/origin/master
else
# not currently on master: use fancy tricks to update
git fetch -p &&
git fetch . refs/remotes/origin/master:refs/heads/master &&
git checkout master
fi
The above, while untested, should be suitable as a shell script. If you have Git installed, you have the ability to run shell scripts—or you can turn the above into a very long Git alias, using ! and the appropriate set of semicolons.
I was doing some work in my repository and noticed a file had local changes. I didn't want them anymore so I deleted the file, thinking I can just checkout a fresh copy. I wanted to do the Git equivalent of
svn up .
Using git pull didn't seem to work. Some random searching led me to a site where someone recommended doing
git checkout HEAD^ src/
(src is the directory containing the deleted file).
Now I find out I have a detached head. I have no idea what that is. How can I undo?
Detached head means you are no longer on a branch, you have checked out a single commit in the history (in this case the commit previous to HEAD, i.e. HEAD^).
If you want to delete your changes associated with the detached HEAD
You only need to checkout the branch you were on, e.g.
git checkout master
Next time you have changed a file and want to restore it to the state it is in the index, don't delete the file first, just do
git checkout -- path/to/foo
This will restore the file foo to the state it is in the index.
If you want to keep your changes associated with the detached HEAD
Run git branch tmp - this will save your changes in a new branch called tmp.
Run git checkout master
If you would like to incorporate the changes you made into master, run git merge tmp from the master branch. You should be on the master branch after running git checkout master.
If you have changed files you don't want to lose, you can push them. I have committed them in the detached mode and after that you can move to a temporary branch to integrate later in master.
git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work
Extracted from:
What to do with commit made in a detached head
A solution without creating a temporary branch.
How to exit (“fix”) detached HEAD state when you already changed something in this mode and, optionally, want to save your changes:
Commit changes you want to keep. If you want to take over any of the changes you made in detached HEAD state, commit them. Like:
git commit -a -m "your commit message"
Discard changes you do not want to keep. The hard reset will discard any uncommitted changes that you made in detached HEAD state:
git reset --hard
(Without this, step 3 would fail, complaining about modified uncommitted files in the detached HEAD.)
Check out your branch. Exit detached HEAD state by checking out the branch you worked on before, for example:
git checkout master
Take over your commits. You can now take over the commits you made in detached HEAD state by cherry-picking, as shown in my answer to another question.
git reflog
git cherry-pick <hash1> <hash2> <hash3> …
Detached head means:
You are no longer on a branch,
You have checked out a single commit in the history
If you have no changes: you can switch to master by applying the following command
git checkout master
If you have changes that you want to keep:
In case of a detached HEAD, commits work like normal, except no named branch gets updated. To get master branch updated with your committed changes, make a temporary branch where you are (this way the temporary branch will have all the committed changes you have made in the detached HEAD), then switch to the master branch and merge the temporary branch with the master.
git branch temp
git checkout master
git merge temp
HEAD is a pointer, and it points — directly or indirectly — to a particular commit:
Attached HEAD means that it is attached to some branch (i.e. it points to a branch).
Detached HEAD means that it is not attached to any branch, i.e. it points directly to some commit.
In other words:
If it points to a commit directly, the HEAD is detached.
If it points to a commit indirectly, (i.e. it points to a branch, which in turn points to a commit), the HEAD is attached.
To better understand situations with attached / detached HEAD, let's show the steps leading to the quadruplet of pictures above.
We begin with the same state of the repository (pictures in all quadrants are the same):
Now we want to perform git checkout — with different targets in the individual pictures (commands on top of them are dimmed to emphasize that we are only going to apply those commands):
This is the situation after performing those commands:
As you can see, the HEAD points to the target of the git checkout command — to a branch (first 3 images of the quadruplet), or (directly) to a commit (the last image of the quadruplet).
The content of the working directory is changed, too, to be in accordance with the appropriate commit (snapshot), i.e. with the commit pointed (directly or indirectly) by the HEAD.
So now we are in the same situation as in the start of this answer:
If you made changes and then realized that you are on a detached head, you can do: stash -> checkout master -> stash pop:
git stash
git checkout master # Fix the detached head state
git stash pop # Or for extra safety use 'stash apply' then later
# after fixing everything do 'stash drop'
You will have your uncommited changes and normal "attached" HEAD, like nothing happened.
Here's what I just did after I realized I was on a detached head and had already made some changes.
I committed the changes.
$ git commit -m "..."
[detached HEAD 1fe56ad] ...
I remembered the hash (1fe56ad) of the commit. Then I checked out the branch I should have been on.
$ git checkout master
Switched to branch 'master'
Finally I applied the changes of the commit to the branch.
$ git cherry-pick 1fe56ad
[master 0b05f1e] ...
I think this is a bit easier than creating a temporary branch.
When you check out a specific commit in git, you end up in a detached head state...that is, your working copy no longer reflects the state of a named reference (like "master"). This is useful for examining the past state of the repository, but not what you want if you're actually trying to revert changes.
If you have made changes to a particular file and you simply want to discard them, you can use the checkout command like this:
git checkout myfile
This will discard any uncommitted changes and revert the file to whatever state it has in the head of your current branch. If you want to discard changes that you have already committed, you may want to use the reset command. For example, this will reset the repository to the state of the previous commit, discarding any subsequent changes:
git reset --hard HEAD^
However, if you are sharing the repository with other people, a git reset can be disruptive (because it erases a portion of the repository history). If you have already shared changes with other people, you generally want to look at git revert instead, which generates an "anticommit" -- that is, it creates a new commit that "undoes" the changes in question.
The Git Book has more details.
Since "detached head state" has you on a temp branch, just use git checkout - which puts you on the last branch you were on.
you probably did git reset --hard origin/your-branch.
Try to just git checkout your-branch
Being in "detached head" means that HEAD refers to a specific unnamed commit (as opposite to a named branch) (cf: https://git-scm.com/docs/git-checkout section Detached head).
In reality, this means that you have checked out a commit but there is no branch name associated with it.
You may choose to only create a new branch associated with your commit by
git branch new-branch-name.
This allows you to save your current state in a new branch named new-branch-name and not be in a detached head state anymore.
Or if you would like to come back to the previous state, you need to select the branch that was selected before by
git checkout #{-1}
To further clarify #Philippe Gerber's answer, here it is:
Before cherry-pick, a git checkout master is necessary in this case. Furthermore, it is only needed with a commit in detached head.
Addendum
If the branch to which you wish to return was the last checkout that you had made, you can simply use checkout #{-1}. This will take you back to your previous checkout.
Further, you can alias this command with, for example, git global --config alias.prev so that you just need to type git prev to toggle back to the previous checkout.
Detached head means you have not checked out your branch properly or you have just checked out a single commit.
If you encounter such an issue then first stash your local changes so that you won't lose your changes.
After that... checkout your desired branch using the command:
Let's say you want branch MyOriginalBranch:
git checkout -b someName origin/MyOriginalBranch
To add to #ralphtheninja's answer. If you get this message after using git checkout master:
Please commit your changes or stash them before you switch branches.
Aborting
Then you can simply force the checkout using the -f flag as follows:
git checkout -f master
Apparently this will result in losing all the changes made in the detached mode. So be careful when using it.
This approach will potentially discard part of the commit history, but it is easier in case the merge of the old master branch and the current status is tricky, or you simply do not mind losing part of the commit history.
To simply keep things as currently are, without merging, turning the current detached HEAD into the master branch:
Manually back up the repository, in case things go unexpectedly wrong.
Commit the last changes you would like to keep.
Create a temporary branch (let's name it detached-head) that will contain the files in their current status:
git checkout -b detached-head
(a) Delete the master branch if you do not need to keep it
git branch -D master
(b) OR rename if you want to keep it
git branch -M master old-master
Rename the temporary branch as the new master branch
git branch -M detached-head master
Credit: adapted from this Medium article by Gary Lai.
Git told me how to do it.
if you typed:
git checkout <some-commit_number>
Save the status
git add .
git commit -m "some message"
Then:
git push origin HEAD:<name-of-remote-branch>
I was in a similar situation.
For some reason I ended up with a detached head - I had made commits on the same path as the branch I thought I was on - eg HEAD was a child of the branch tag but for some reason the branch tag had stayed back at a historic commit... possibly because I had pushed??
It wouldn't let me push because I wasn't considered to be on the branch I thought I was on.
I didn't want to change any of my history or do any cherry picking and I'd just spent about 8 weeks working on the branch so reset --hard was making me a bit nervous!
The solution was just to do the following:
git branch -f myStuckBranch HEAD
git checkout myStuckBranch
You need to do the checkout even though HEAD and myStuckBranch are now pointing at the same thing because you are still considered to be in the detached head state (not on a branch)
I'm not an expert with git (having mostly used mercurial which would never create this weird situation) but my understanding of this command is that it just says
"change myStuckBranch to point at HEAD".
I routinely find myself using this command to merge in changes from master after fetching without having to swap my working directory - otherwise it tries to use the old (uninteresting) version of master:
git fetch
git branch -f master origin/master -- err yeah don't just ignore what's been going on remotely - eg point my master at the real master
git merge master -- merge the changes into my local branch
It's a bit annoying to have to manually have to do that all the time but still better than having to change your working directory just to update another branch in order to merge in changes from it.
Normally HEAD points to a branch. When it is not pointing to a branch instead when it points to a commit hash like 69e51 it means you have a detached HEAD. You need to point it two a branch to fix the issue. You can do two things to fix it.
git checkout other_branch // Not possible when you need the code in that commit hash
create a new branch and point the commit hash to the newly created branch.
HEAD must point to a branch, not a commit hash is the golden rule.
This was a confusing thing to me when I started to work with git and later I figure out why this is happening and what is the best way to deal with such a situation.
The root cause for such occurrence is that normally git HEAD is always pointing to some branch and when you try to point the HEAD to some specific commit, you put HEAD into a detached HEAD state.
When HEAD is attached state -
cat .git/HEAD # output--> ref: refs/heads/master or ref: refs/heads/main
When HEAD is detached state -
cat .git/HEAD # output--> b96660a90cad75867453ebe1b8d11754bbb68b0e <commit hash>
Solution -
git stash # Temporarily shelves (or stashes) changes
git branch # Find your default branch
git switch master # Point HEAD to master or main branch
git stash pop # Apply all the changes you had previously
I wanted to keep my changes so, I just fix this doing...
git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH
that work for me
When you're in a detached head situation and created new files, first make sure that these new files are added to the index, for example with:
git add .
But if you've only changed or deleted existing files, you can add (-a) and commit with a message (-m) at the the same time via:
git commit -a -m "my adjustment message"
Then you can simply create a new branch with your current state with:
git checkout -b new_branch_name
You'll have a new branch and all your adjustments will be there in that new branch. You can then continue to push to the remote and/or checkout/pull/merge as you please.
Realizing I had a detached head without knowing how I managed to get it (like three commits away), I also found out that trying to merge, rebase or cherry-pick triggered hundreds of merge-conflicts, so I took a different approach:
(Assuming everything is committed (working tree is "clean"))
Save my commit messages: git log > /tmp/log
Save my working tree: mkdir /tmp/backup && cp -a all_my files_and_directories /tmp/backup
Revert to master: git checkout master
Remove all the working files and directories: rm ...
Use the backup: cp -a /tmp/backup/. .
git add and git commit using messages from saved /tmp/log, maybe repeating it with different sub-sets of files...
The disadvantage is that you loose your commit history if one file was changed multiple times since master, but in the end I had a clean master.
Git : You are not currently on a branch.
Time to time Git shows :
To push the history leading to the current (detached HEAD)
state now, use
git push origin HEAD:<name-of-remote-branch>
It means :
" HEAD have no branch "
To fix that run 2 commands :
git branch -f {{your_working_branch}} HEAD -- set branch to your head
git checkout {{your_working_branch}} -- checkout==switch branch
The detached HEAD means that you are currently not on any branch. If you want to KEEP your current changes and simply create a new branch, this is what you do:
git commit -m "your commit message"
git checkout -b new_branch
Afterwards, you potentially want to merge this new branch with other branches. Always helpful is the git "a dog" command:
git log --all --decorate --oneline --graph
git pull origin master
worked for me. It was just about giving remote and branch name explicitly.
This works for me, It will assign a new branch for detached head :
git checkout new_branch_name detached_head_garbage_name
With git rebase you can move your HEAD to the desired commit
Suppose you have your branch in a detached state, like this:
* bfcb8f9 Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 (HEAD -> master) Commit 2 --amend
|/
* 1818f91 Commit 1
The detached head was created by rebasing by mistake, pointing to a detached commit, which was created previously due a git commit --amend command.
If you want to move your HEAD ref to the most recent commit, apply a rebase with the desired HASH commit you want to point to. In this example, the hash is of the most recent commit:
git rebase bfcb8f9
and this will leave your branch with its HEAD poiting to the desired commit (the most recent in this case):
* bfcb8f9 (HEAD -> master) Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2 --amend
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 Commit 2
|/
* 1818f91 Commit 1
If you hate head and wanna go back to main instead:
git checkout main
If you love head but just wish main tracked it:
git checkout -B main HEAD
(This works with any branch name, not just main, and for any commit pointer, not just HEAD.)
Currently had issues with 'UserInterfaceState.xcuserstate' while working with another developer and using Git as our source control. I realized early on that .gitignore wasn't ignoring that file and I decided to remove/untrack it with 'git rm --cached'. Before executing the command, I stashed my current changes to:
Keep my current changes
Create a quick commit that reflects the removal of UserInterfaceState.xcuserstate
I created the commit the reflected the removal of 'UserInterfaceState.xcuserstate' and proceeded with 'git stash apply'. This was the error that I received:
needs merge
unable to refresh index
I'm aware that the stash still has UserInterfaceState.xcuserstate but I was under the impression that Git would merge the newly committed state of the master branch with the stash and force me to resolve the merge conflict.
How would I be able to merge the stash to regain my previous work to the newly committed master branch the no longer has nor tracks UserInterfaceState.xcuserstate?
Whenever you have a stash that won't apply, I recommend turning that stash into a branch.
To do that, first make sure you have no uncommitted work. This means you should now commit whatever you're doing, or stash it—the latter is a bit ironic and weird but works fine, as long as you remember that the stash you're converting has now been renumbered. Now that everything is "clean", pick the troublesome stash by its ID—stash#{1} or stash#{6} or whatever if necessary, or just the default if it's the current or only stash—and use that ID (or the default) as an argument to the git stash branch command:
$ git stash branch newbranch stash#{3}
You're now in a state where you can run git status, then maybe git commit, or git add and git commit, etc—your stash#{3} stash has been re-loaded into the index, as if you had run git stash apply --index, and into your work-tree as if by the same command. Once you make the commit(s), your new branch is ready to be used however you like.
(In fact, Git really did run the command: first, Git ran git checkout of the appropriate commit. Then Git ran git stash apply --index on the stash, which restored the saved index and the saved work-tree. Then, having succeeded at the applying, Git ran git stash drop on that saved stash.)
In this case, after git stash branch name stash, you'll probably want one git add and git commit, which will save all of your work including the pesky not-removed, maybe-modified-maybe-not UserInterfaceState.xcuserstate file. But now you can git checkout the branch you were working on, apply and drop the temporary stash you made if you made one, and git cherry-pick -n the commit on that new branch you made from your troublesome stash. If that commit has no changes to the pesky file, and the pesky file doesn't exist here, the cherry-pick is likely to go pretty smoothly and you'll be all set.
Discussion
This all makes a certain amount of sense once you realize that (a) a git stash object is just a clump of commits; (b) commits always record their parent commits; and (c) a branch is just a series of commits designated by a branch name identifying the last commit that is to be considered part of the branch.
If the way git stash made its little clump-of-commits were normal, you'd have:
...--o--o--*--o <-- your-branch
\
i--w <-- stash
and hence the stash would really be just like any branch, except for the fact that refs/stash does not start with refs/heads/ (compare with refs/heads/your-branch, which obviously does start with refs/heads/). Here, * is the commit that you were on when you ran git stash. You added one more commit, which is the one just to the right of the *. The i and w commits here would contain the index and work-tree states as of when you ran git stash.
The tricky part is that git stash doesn't make i and w like this at all. Instead, it makes:
...--o--o--*--o <-- your-branch
|\
i-w <-- stash
That is, the saved work-tree state appears to be a merge commit, saving the result of merging your index commit i and the commit you were on when you ran git stash (commit *). It isn't really a merge, in that it's not what you'd get by running git merge: the stash code is just abusing the merge-commit format, to make it easier for the stash code later.
Fortunately, git stash branch knows just how to de-abuse the format. It:
checks out commit *;
makes a new branch name to remember where you are now; and
applies the stash, keeping its index and work-tree components separate (just as they were when you saved the stash) in case that's what you intended.
So now you have:
o <-- your-branch
/
...--o--o--* <-- new-branch
with i in your index (ready to be committed) and w back in your work-tree (ready to be git add-ed to update your index, after which w will be in your index and ready to be committed). Commit *, of course, has the pesky file in it, so leave the pesky file where it is with no changes, add and commit everything else, and you get:
o <-- your-branch
/
...--o--o--*--W <-- new-branch
where W is a regular ordinary commit of the work-tree state you had, ready to be given to git cherry-pick (probably with -n) or used however you like.
Eventually, you can simply delete the branch new-branch (which you probably want to call by some other name) and commit W will be abandoned and will eventually disappear entirely.