Removing sensitive data from Git. "fatal: ambiguous argument 'rm'" - linux

I'm trying to run this command:
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch filename.js' --prune-empty --tag-name-filter cat -- --all
but I keep getting this error:
fatal: ambiguous argument 'rm': unknown revision or path not in the working tree
.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

It depends on the shell you are using.
On Windows, with msysgit for instance, see issue 477:
Single quotes do not have a special meaning with CMD. Do not expect that they work
the same as with a POSIX shell. Call filter-branch like this:
git filter-branch --commit-filter "GIT_COMMITTER_NAME=void GIT_AUTHOR_NAME=void GIT_COMMITTER_EMAIL=just.a.test#kernel.org GIT_AUTHOR_EMAIL=just.a.test#kernel.org; git commit-tree \"$#\"" HEAD
Multiple lines:
git filter-branch --commit-filter "GIT_COMMITTER_NAME=void \
GIT_AUTHOR_NAME=void \
GIT_COMMITTER_EMAIL=just.a.test#kernel.org \
GIT_AUTHOR_EMAIL=just.a.test#kernel.org; \
git commit-tree \"$#\"" HEAD
As mentioned in "How to pass a programmatically generated list of files to git filter-branch?"
Each argument to the various ...-filters needs to be a single string. That string is saved as a shell variable.
So make sure 'git rm --cached --ignore-unmatch filename.js' is considered a string in the shell you are in.
As Constantine Ketskalo points out in the comments:
Windows 10, PyCharm, GitPython, same command as in question.
Simply changed ' to " inside the string and it worked!

On windows, you have to use double quote " instead of single '

Related

Alias for 'git stash drop' in zsh

I want to make an alias to drop a git stash in zsh shell. The stash no. which I want to drop should be passed as an argument to my function call.
I have tried below but it is failing -
function gd() {
if [ -n "$1" ]
then
git stash drop "$1"
else
echo 'Enter stash no to drop'
fi
}
It gives me below error -
fatal: ambiguous argument '0': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
Seems I am not passing the argument correctly and it is being treated as a string.
How can I make this work?
#ShantanuTomar : You don't define any alias, which is not a bad thing in the first place, because a function is more flexible anyway, but if you really want to have an alias, the command to define it would be
alias gd='git stash drop'
Aside from this, your function definition is fine, though you don't need to quote your variables. It doesn't harm doing so, though.
The error message says that the stash you provided, does not exist. Use
git stash list
to get a list of the available stashes.
Try
git stash drop $1
But, as commented, there won't be any kind of conversion done by zsh alone.
So, make sure to use a recent enough Git:
git stash using numbers (then interpreted as stash#{n}) is only supported since Git 2.11 (Q4 2016)
there was a bug associated with git stash and its index, fixed in Git 2.23

git diff for *.cpp files prints nothing in one repository

Once the command git diff *.cpp just stopped printing anything in one repository, despite git diff *.h works fine. git diff works fine for *.cpp files.
What could it be?
The fix is to be careful to run, e.g.:
git diff '*.cpp'
or:
git diff \*.cpp
or more formally:
git diff -- '*.cpp'
or similar.
What's going on here?
Missing from the question: the desired output was a diff for subdir/subfile.cpp, but the top level of the work-tree contained one file named file.cpp or similar.
The problem stems from the fact that you're using a Unix/Linux-style shell, which expands * and other wildcard or glob characters before running the command you enter at the command line. But there is a bit of subtlety here as well.
Because there exists a file named file.cpp in the current directory, when you run:
git diff *.cpp
the shell replaces *.cpp with the names of all the files whose name ends with .cpp, and therefore runs:
git diff file.cpp
Git then dutifully produces the diff—or in this case, no diff since there is no difference—for the one file named file.cpp.
When there are no files named file.cpp or zorg.cpp or similar in the top level directory, however, this shell simply invokes git with arguments diff and *.cpp, as if you had quoted the asterisk. This gives Git the chance to expand the *.cpp argument, and when Git expands it, it does so in a different way than the shell.
Why use --?
The git diff command takes a number of options, such as -s, -p, -w, --name-status, --name-only, and so on.
Depending on what files you have, suppose you want a diff listing for the file named -z in the current directory. If you then run:
git diff -z
Git thinks you mean to supply the -z option, rather than to get a diff listing for the file named -z. A similar problem applies if you want diffs for -z* and the like.
In general, you can work around this problem by using the file name ./-z instead of just -z. Since ./-z does not start with -, Git is not fooled into thinking it's an option. But this problem is more general, and strikes in other cases (other commands) as well. For instance, suppose you have a file named develop and you run:
git checkout develop
Git will think you mean to check out the branch named develop.
All Git commands accept -- as a separator, generally meaning there no more options: anything after this point is an argument instead. For git diff, anything after -- is treated as a pathspec, which includes doing glob expansion, provided the glob characters made it past the shell.
This is what the syntax description in the SYNOPSIS section of the git diff documentation means:
git diff [<options>] [<commit>] [--] [<path>...]
git diff [<options>] --cached [<commit>] [--] [<path>...]
git diff [<options>] <commit> <commit> [--] [<path>...]
git diff [<options>] <blob> <blob>
git diff [<options>] --no-index [--] <path> <path>
The square brackets indicate that something is optional, so all the options are optional. The angle brackets indicate that some argument should be replaced with a string that meets the requirements of the type inside the brackets. The literal -- or other literal options imply that you should type those characters literally—so git diff --cached requires the literal string --cached, for instance. Last, the ... means "repeat the previous as often as you like".
Since the literal string -- is optional, you don't have to enter it—but if you do, everything after it must have the form of a <path>. That form is quite general: almost any character is valid. The documentation is missing a cross-reference to the definition of a pathspec, though (and probably should use <pathspec>, not just <path>, here). The full description of pathspecs is in the gitglossary.
So I have one .cpp file in the repository root directory, and so git diff *.cpp now prints changes only for this file, while git diff '*.cpp' works fine for all files in subdirectories.

How to check for the presence of a git repository in a directory using bash script

I am trying to work with git on my project.
I want to set up the terminal such that whenever I cd into a directory that contains a git project, the terminal should indicate which git branch I am currently on.
If there is a git project, the terminal show only the name of the branch,
for example
(master) $
otherwise it should show the current directory path.i.e
username#machinename:path/to/directory $
I found a similar question answered here but i don't know how to modify the answer to suit my need, because am not good with bash scripting.
Any suggestion will be highly appreciated.
Have a look at this project https://github.com/jimeh/git-aware-prompt, it should solve your whole problem and when not, you can change it to meet your needs. Main logic is in prompt.sh.
To find current git branch name in directory, you can always run
git rev-parse --abbrev-ref HEAD
It will return branch name, HEAD (when detached) or nothing when directory is not par of git repository. If you need only this information, you can update your .bashrc. Edit variable PS1, which is bash prompt format.
PS1='(`git rev-parse --abbrev-ref HEAD 2> /dev/null`) \$ '
This is example how to display branch name anywhere in the prompt. The git script will help you and recognize whether to show branch or directory. It will update your PROMPT_COMMAND, which is called every time the bash prompt line is displayed, by checking for git branch name which you can then use in PS1 as a variable. You can then update your existing PS1='${debian_chroot:+($debian_chroot)}\u#\h:\w\$ ' to
PS1='${debian_chroot:+($debian_chroot)}\u#\h:\w \(\$git_branch\)\$ '
You have many tools which do it.
myzsh for example or just a simplt bash that you add to your bashrc
http://martinvalasek.com/blog/current-git-branch-name-in-command-prompt
example:
function parse_git_branch () {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
RED="\[\033[0;31m\]"
YELLOW="\[\033[0;33m\]"
GREEN="\[\033[0;32m\]"
NO_COLOR="\[\033[0m\]"
PS1="$GREEN\u#\h$NO_COLOR:\w$YELLOW\$(parse_git_branch)$NO_COLOR\$ "
The Git package in Linux usually comes with a prompt script that you can use to see the repository status. To enable it, source the git-prompt.sh script in a shell startup file (e.g. ~/.bashrc), then set a custom prompt with the %s parameter. For example, in ArchLinux you could do:
[ -r /usr/share/git/completion/git-prompt.sh ] && . /usr/share/git/completion/git-prompt.sh
PS1='[\u#\h \W$(__git_ps1 " (%s)")]\$ '
When changing to a directory of a Git repository, the prompt will change to show the branch name. Extra details can be set to be shown by the prompt (see the link above).

Why isn't git reading the added file?

I was reading an article that told me to add a file and place it in my path. Not knowing what the author meant by path, i simply put it in my root directory.
Trying to run 'git diffall', git says diffall is not a command, any ideas? Thanks in advance.
The article snippet for more information:
Write the following code to a file called git-diffall and place in your path (I put it in >…/my-git-install-dir/cmd/ )
#!/bin/sh
git diff --name-only "$#" | while read filename; do
git difftool "$#" --no-prompt "$filename" &
done
And run it in git (with usual diff input parameters), for example:
git diffall
git diffall HEAD
your 'path' is the collection of directories where the system looks for executables. To see it, simply execute echo $PATH at the commandline. Then put your script in one of those directories.

How do you pass a file list to the linux zip command

I'm using Git for version control and unlike SVN I have not come across an inherent means of performing an export of changed files between 2 revisions, branches or tags.
As an alternative I want to use the linux zip command and pass it a set of file names, however the file names are the result of another command git diff. Below is an example of what I am trying to achieve:
zip /home/myhome/releases/files.zip git diff --name-only -a 01-tag 00-tag
However the above does not work as I guess the 'zip' command sees the git operation as part of its command options.
Does someone know how I can make something like the above work?
Thanks
You need to execute the git command in a sub-shell:
zip /home/myhome/releases/files.zip `git diff --name-only -a 01-tag 00-tag`
# another syntax (assuming bash):
zip /home/myhome/releases/files.zip $(git diff --name-only -a 01-tag 00-tag)
Another option is the xargs command:
git diff --name-only -a 01-tag 00-tag | xargs zip /home/myhome/releases/files.zip
If you're in a git shell (bash) you can also do this:
git diff -–name-only commit1 commit2 | zip ../Changes.zip –#
Works for me on Windows and Unix based systems.

Resources