Watch for file changes and add changes to github? - macos

On OSX I want to create a script that 'when a file changes, automatically runs
git add [FILES CHANGED];
git commit -m "Changing ${file names}";
git push -u origin master"
I understand there is fswatch, however, this keeps a process running.
Maybe I can try running "git status" and if != "On branch master
nothing to commit, working directory clean" then automatically push to Github?

I know this is an old thread, but I was also looking for an alternative solution and found rerun2. Perhaps it will also be useful to somebody else.
https://github.com/tartley/rerun2
From Tartley's readme:
It runs COMMAND every time there's a filesystem modify event within
your current directory (recursive). For example, it can re-run tests
every time you hit 'save' in your editor. Or it can re-generate
rendered output (html, SVG, etc) every time you save the source (e.g.
Markdown or GraphViz dot).
COMMAND needs to be a single parameter to rerun, hence if it contains
spaces, either quote the whole thing:
rerun "ls ~"
or escape them:
rerun ls\ ~
How to implement:
If you take your code, and put it inside an update.sh script:
#!/usr/bin/env bash
git add -u
git commit -m "Automatic update of modified files" && git push
Make it executable:
chmod u+x gitpush.sh
Create an alias to make things easier:
alias gitpush=/path/to/gitpush.sh:
Open the terminal, got to the directory you want to watch and run the command:
rerun gitpush
Now it will execute gitpush everytime files changes in that directory.

If you're willing to give up automatically responding to file modifications, you could just periodically run (e.g., via a crontab entry or something):
git add -u
git commit -m "Automatic update of modified files" && git push
The git add -u will stage any modified files, and "git commit" will only be successful if there are modifications to commit.
If you also want to pick up new files, you could use git add -A instead.

Related

How to diff before each commit without going into interactive mode?

Say you do git status and you get back a list of files which you want to check one by one and then commit them one by one.
Or you do a git diff on a directory and want to go and commit directly after your inspection. How to do that with a simple trick?
If you are in a GUI environment. You can launch "git gui" from the console..
This would launch a window, where the left pane would contain the list of changed files. Selecting any of them, shows you the diff.
You can add files by clicking on the icon to the left of the file name and later commit it from the same window.
Hope it helps.
Note: diff + commit would not work because you have not added anything to the index.
As commented, git add -i or git add -p (--patch) will give you a diff view, with the possibility to add or skip each diff hunk.
Then you can commit the modified index.
UPDATE 2020:
After fiddling around I decided to install and use ydiff.
Doing ydiff -s shows a diff side by side in the terminal.
No brainer check it out here and don't mind my old answer:
https://github.com/ymattw/ydiff
[ OLD
]
Git diff before your commit?
Simple solution thinking outside of the box:
Stick this in your .bashrc or .zshrc:
gdiffy() { git diff $1 && git add $1 && git commit $1; }
First it will pop open up a diff, when you close it, it will allow you enter a commit message.
usage example:
gdiffy config/database.yml
or
gdiffy .

Git for Windows "No tags file" Response from "git diff" Command

Git version: 2.14.2.2
Whenever I run git diff on a repository I am greeted with the response No tags file. I have tried running the command on multiple repositories, multiple consoles (Cmd, PowerShell, MINGW64, Visual Studio Command Prompt) and all have the same response.
Strangely, the git log command also fails. Many other commands work, however, such as git status, git pull, etc. It seems to be only log and diff.
I have uninstalled Git entirely and reinstalled. Restarted my system. Tried referencing the git.exe directly (which yields the exact same response). Nothing is working and I have not seen this error anywhere else. I compared my user configs with those of a colleague and they are identical.
Some portion of the command executes properly, because if I supply two commit hashes, and I intentionally break one, the response I receive is:
It seems like another program may be hijacking the git diff command. I believe this because I'm not sure "No tags file" is even a possible Git response. Not sure what else it would be.
To make things even more confusing- my ultimate goal is to run the git diff within the context of an msbuild and it DOES EXECUTE CORRECTLY. Now, I could be satisfied with this, but I need to modify the diff command slightly, and running a full build each time is not productive, nor easy to troubleshoot. There is a task within the build script that runs an Exec command and it has no issues performing the diff. I'm also able to execute a Diff Against Current within SourceTree, which to the best of my knowledge, runs a git diff behind the scenes.
Any help would be very much appreciated.
:: Edits ::
Various commands:
git diff HEAD~1 HEAD
git diff master~1 master
git diff <commit-hash-1> <commit-hash-2>
git log HEAD~1..HEAD
git log master~1..master
git log <commit-hash-1>..<commit-hash-2>
Output:
Every one of the commands above returns the same No tags file response, in all of my repos.
Cat Head:
cd .git
cat HEAD
ls -R refs
Output:
New Repo:
mkdir testrepo
cd testrepo
git init
echo "file1" > file1.txt
git add .
git commit -m "initial commit of file1.txt"
echo "Hi there!" > file2.txt
git add .
git commit -m "added file2.txt"
git log
git diff HEAD~1 HEAD
Output:
git config -e:
git config --global -e:
::Edits 2::
I uninstalled all of my diffing/source control tools (SourceTree, Git, SVN, WinMerge, KDiff). Installed the portable version of Git. Opened CMD to a repo, put in full path to the git.exe portable and it still returned the No tags file response.
I also reviewed all of my path variables for: git, vim, ming, mintty and anything else that seemed suspect, but didn't find any.
I have restarted after performing all steps, and yet the problem persists.
::Edits 3::
I have a different user on my laptop, switched to that user and the git diff works properly, so clearly there is something with my main user that is conflicting. Will continue to look into my User directory for issues.
Here are the steps I'd take in this situation:
Try the following and check the response:
git diff HEAD~1 HEAD
git diff master~1 master
git diff <commit-hash-1> <commit-hash-2>
Try the same with log:
git log HEAD~1..HEAD
git log master~1..master
git log <commit-hash-1>..<commit-hash-2>
I'm actually guessing that your refs are messed up, which means that the direct hashes might work, but the HEAD and/or master one may not.
Look into the .git/refs folder
From the main repo folder:
cd .git
cat HEAD
ls -R refs
Hopefully, HEAD is pointing to a branch, and if master is checked out, cat HEAD output should look like:
ref: refs/heads/master
Then, the ls -R refs, should show a heads folder, with files for each of your local branches (i.e. master and possibly others). You also likely have refs/remotes and refs/tags directories.
If any of these things are radically different or missing, that could be your issue...
Since you have reinstalled git, create a brand new repo and try the same commands:
mkdir testrepo
cd testrepo
git init
echo "file1" > file1.txt
git add .
git commit -m "initial commit of file1.txt"
echo "Hi there!" > file2.txt
git add .
git commit -m "added file2.txt"
git log
git diff HEAD~1 HEAD
If this last one works, then git is likely working okay, but some tool you have is messing things up.
Post your config from git config -e and git config --global -e - maybe we can see something?
When googling for the "No tags file" message, the first results I get all talk about vi.
I do not understand why git would try to execute vi when running git diff or git log, could it be that your system is configured to use vi as a pager ?
# some possible places which could influence that :
echo $PAGER
echo $GIT_PAGER
git config --get core.pager
When digging in the documentation for less, I found that less can use a ctags file, to spot "the file that contains this tag".
So you can also look at the list of variables that influence the behavior of less :
# from bash :
# env will list all the defined environment variables
env
# the ones that impact 'less' should contain "LESS" in their names :
env | grep LESS

Git pre-commit hook is not running on Windows

I'm just starting to look into Git hooks, but I can't seem to get them to run.
I set up a local repository, so there is now a '.git' directory in my project folder. I have added a '.cmd' file into the C:/path/to/my/project/.git/hooks directory named 'pre-commit.cmd'. Here is the contents of this file:
echo "HOOK RUNNING"
echo. 2>C:/path/to/my/project/.git/hooks/EmptyFile.txt
This should echo the text "HOOK RUNNING" and create an empty text file in that directory. However, if I commit changes through my IDE (NetBeans) or use Git Bash to commit, neither of them seem to run my pre-commit hook, as no file is created.
My understanding is that all you have to do to get a hook to run is add an executable with the name of the hook (as I have done). Am I doing something wrong?
Note: This is on a Windows 7 PC.
Name your hook pre-commit (without any file extension).
And add #!/bin/sh on the first line or #!/bin/bash.
You probably don't have the permissions to run the pre-commit file
Run in your terminal:
chmod +x .git/hooks/pre-commit
Thanks to #vaughan for giving the idea
TL;DR
Git hooks work on Git for Windows by default assuming the Git hook script is simple.
Background of Git and Windows
Please Note: Git was made for shell interpretation; thus, using Git hooks on a Windows command prompt or Windows-made PowerShell will inherently have its flaws, and complete interoperability is not to be expected.
Using Git hooks on Windows is possible, but it has many drawbacks.
Git for Windows uses a shell emulator that makes Bash and shell commands possible. This means that when a Git hook is activated by Git, the Windows version will run the command using the shell emulator. Which in turn, will convert those shell commands to commands that the Windows operating system can understand. Meaning, simple shell scripts will work right off the bat. For example, the Git hook pre-commit that ships with an initialization of a Git repository can be run without any modification.
Example of default behavior
Initialize a Git repository with the command git init
Navigate to the Git hooks directory with the command cd .git\hooks
This directory holds all the Git hook scripts. Create a file named pre-commit. Note:
The name of the file is important
Replace the contents with the following shell script
#!/bin/sh
echo "Hello, World!"
Navigate back to your root directory of the project and create a file named test.txt using the command echo "something" > text.txt
Stage the file to commit using the command git add test.txt
Commit the change and watch the pre-commit hook activate using the command git commit -m "test commit"
Verify the output to look like the following
git commit -m "test commit"
Hello, World!
[master f00ccea] test commit
Example of bad behavior
When using a very advanced shell script to do things in Git hooks, Windows shell interpretation doesn't always stack up. For example, when using the Husky Git hook plugin for NPM, along with the Prettier formatter, the commands do not map 1-1. Meaning that your pre-commit Git hook will fail on Windows.
Answering user1578653's question
A Git hook is an executable script; however, you are using a command prompt script (.cmd) and not a shell script (.sh). If you would like this behavior you described on a Windows operating system then create the file named pre-commit and place it in the .git\hooks directory (relative to the project you are working on). Then place the following content in that file.
.git\hooks\pre-commit
#!/bin/sh
echo "HOOK RUNNING"
thisCausesError 2> .git/hooks/EmptyFile.txt
You will notice that the Git hook works and outputs the words HOOK RUNNING to the console, and the thisCauseError will print an error message to standard error that will be printed to the file EmptyFile.txt.
In my case, I had set core.hooksPath to the wrong directory.
Resetting it with git config --global core.hooksPath '~/.githooks' solved the issue :)
You can verify your hooks path using git config --get core.hooksPath
For me, I tried to run a .bat file.
I discovered that backslashes need to be escaped:
For example:
#!/bin/bash
C:\\somefolder\\somefile.bat
For me, none of the previous solutions worked. I moved the pre-commit file from hooks to some other location, effectively deleting the file from hooks.
That worked for me :D
In my case, where I did npm install and accidentally deleted the .git folder, npm install pre-commit --save worked.
If it helps anyone:
I was getting the following error:
error: cannot spawn .git/hooks/pre-commit: No error
It turned out that in my pre-commit file I did not have 'newline' character after last exit command:
#!/bin/sh
# From gist at https://gist.github.com/chadmaughan/5889802
# Stash any unstaged changes
git stash -q --keep-index
# Run the tests with the Gradle wrapper
./gradlew test --daemon
# Store the last exit code in a variable
RESULT=$?
# Unstash the unstashed changes
git stash pop -q
# Return the './gradlew test' exit code
exit $RESULT
# << must have a newline after the above command >>
I was running a Gradle project on Windows and Gradle commands in the Cmder shell and cmd.
I tried solutions suggested in other answers and it didn't help to fix this problem:
cannot spawn .git/hooks/pre-commit: No such file or directory
The solution, which worked for me, was to rename the file .git/pre-commit.sample to .git/pre-commit and insert the script for formatting changed files with Prettier. The file with the name 'pre-commit' which I have created manually must have had some problems (encoding or end-line symbols remains unclear).

Can't ignore UserInterfaceState.xcuserstate

I'm using Git for Xcode 4 project version control. I've explicitly added ProjectFolder.xcodeproj/project.xcworkspace/xcuserdata/myUserName.xcuserdatad/UserInterfaceState.xcuserstate to .gitignore, but Git it won't ignore it. Any ideas why this is so?
Git is probably already tracking the file.
From the gitignore docs:
To stop tracking a file that is currently tracked, use git rm --cached.
Use this, replacing [project] and [username] with your info:
git rm --cached [project].xcodeproj/project.xcworkspace/xcuserdata/[username].xcuserdatad/UserInterfaceState.xcuserstate
git commit -m "Removed file that shouldn't be tracked"
Alternatively you can use the -a option to git commit that will add all files that have been modified or deleted.
Once you've removed the file from git, it will respect your .gitignore.
In case that the ignored file kept showing up in the untracked list, you may use git clean -f -d
to clear things up.
1.
git rm --cached {YourProjectFolderName}.xcodeproj/project.xcworkspace/xcuserdata/{yourUserName}.xcuserdatad/UserInterfaceState.xcuserstate
2.
git commit -m "Removed file that shouldn't be tracked"
3.
WARNING first try git clean -f -d --dry-run, otherwise you may lose uncommited changes.
Then:
git clean -f -d
All Answer is great but here is the one will remove for every user if you work in different Mac (Home and office)
git rm --cache */UserInterfaceState.xcuserstate
git commit -m "Never see you again, UserInterfaceState"
Had a friend show me this amazing site https://www.gitignore.io/. Enter the IDE of your choice or other options and it will automatically generate a gitignore file consisting of useful ignores, one of which is the xcuserstate. You can preview the gitignore file before downloading.
In case the file keeps showing up even after doing everything mentioned here, make sure that this checkbox in Xcode settings is unchecked:
Just
"git clean -f -d"
worked for me!
Here are some demo & short cuts if you uses GitHub, the basic ideas are the same.
1. Open terminal like this
2. Paste the below command to terminal followed by a space and then paste the path of the .xcuserstate file simply like this
git rm --cached
3. Make sure you have the correct git ignore and then commit the code :)
This works for me
Open the folder which contains the project file project.xcworkspace from the terminal.
Write this command: git rm --cached *xcuserstate
This will remove the file.
For me nothing worked, but this
add this line to your gitignore
*.xcuserdata
Here is one more simple solution if you are using the source tree app.
here are the instructions
1.Right-click on the file which you want to add to the git ignore list and select stop tracking.
again right-click on the same file and you will notice ignore option is now enabled then click on ignore button.
now you can reset or commit your changes for the same file it depends on whether your changes are important or not. changes in the future will not be tracked for the selected file.
Here is a very nice explanation of how to remove the files in question recursively from your git history: http://help.github.com/remove-sensitive-data/
Very useful, because otherwise tools tend to 'hang' while trying to show the diff on those huge files that shouldn't have been checked in the first place...
Here's what you can do (in short) to get rid of the largest stuff:
cd YourProject
git filter-branch --index-filter 'git rm --cached --ignore-unmatch -r YourProject.xcodeproj/project.xcworkspace' HEAD
# see what you want to do with your remote here...
# you can: git push origin master --force
# or you can delete it and push a fresh new one from your cleaned-up local...
rm -rf .git/refs/original
git gc --prune=now
git gc --aggressive --prune=now
Worked very nicely for me :)
For xcode 8.3.3 I just checked tried the above code and observe that, now in this casewe have to change the commands to like this
first you can create a .gitignore file by using
touch .gitignore
after that you can delete all the userInterface file by using this command and by using this command it will respect your .gitignore file.
git rm --cached [project].xcworkspace/xcuserdata/[username].xcuserdatad/UserInterfaceState.xcuserstate
git commit -m "Removed file that shouldn't be tracked"
You can also ignore files from Xcode preferences itself.
Generate gitignore file from https://www.toptal.com/developers/gitignore
Go to Xcode -> Preferences -> Source Control -> Git -> Add all ignore items in the list...Even though UI is not really useful & you have to add all items individually but adding ignore files here surely works.
I think it would be better to write like this.
git rm --cache *//UserInterfaceState.xcuserstate**

How do I execute several git commands in a batch file without terminating after the first command?

I tried to put a series of GIT commands that I always use continuously togeter as batch files so that I don't repeat myself too much. For example, I have this batch file called update_repo_branch.bat to update a local repo and synch a branch with the remote branch:
#echo off
if(%1) == () goto end
if(%2) == () goto end
cd %1
git checkout %2
git fetch origin
git merge oring/%2
:end
Good to be lazy, but what I found is that when a GIT command is finished, it seems to send an exit flag back to terminate whatever is running. Therefore, using a batch file to exectute them all in one go simply doesn't work. Any idea how to work around it?
I'm not sure if this is true for all Windows git packages, but at least some use a git.cmd script as a wrapper around the actual git executables (for example git.exe). So when you're batch file uses a git command, Windows is actually running another batch file.
Unfortunately, when one batch file invokes another, by default it 'jumps' to the invoked batch file, never to return (this is for compatibility with ancient MS-DOS command processors or something).
You can solve this problem in a couple ways:
invoke git in your batch files using the call command to run the git.cmd batch file and return back to yours:
call git checkout %2
call git fetch origin
rem etc...
invoke git in your batch file using the .exe extension explicitly to avoid the git.cmd batch file altogether. For this to work, you might need to make sure that you have your path and other environment variables set the way git.exe expects (that seems to be what git.cmd does in msysgit):
git.exe checkout %2
rem etc...
Assuming you are using msysGit as your Git client you might actually want to use Bash scripts for this. You could place a bash function in your ~/.bashrc (~ is usually your C:\Users\- see here) as follows
update_repo_branch() {
if [ $# != "2" ]; then
echo "Usage: update_repo_branch REPO BRANCH" 1>&2
return 1
fi
cd $1
git checkout $2
git fetch origin
git merge origin/$2
}
You can then run update_repo_branch myrepo cool-branch from the mysysGit shell.
Of course, this won't be accessible from cmd.exe. You will only be able to use it within the msysGit cygwin shell.
As i see from your example you're actually trying to sync your local branch 'branchname' with origin/branchname
For this you don't need any additional scripting, you just have to use git pull instead of sequence git checkout branchname; git fetch origin; git merge origin/branchname
take a look at the docs about tracking branches in git and their benefits.
generally speaking if you have a repo layout like this:
git branch -a
...
master
dev1
dev2
remotes/origin/master
remotes/origin/dev1
remotes/origin/dev2
And your dev1 and dev2 branches are tracking branches for origin/dev1 and origin/dev2 correspondingly then you just need to execute in repository:
git pull
This command will effectively sync up all you local tracking branches with remote ones.
for more see here:
Git pull docs
Git remote branches and tracking branches (Progit book)
Create a notepad file and paste the below content and save with .bat extension.
This script can be use for setting up git first time in a project.
!echo off
git init
git add .
git commit -m "first commit"
git branch -M main
git remote add origin <YOUR_REPO_URL>
git push -u origin main
pause

Resources