Git & Mac: Working with Unicode filenames

I had some problems with Git and the file spec/fixtures/ČeskýÁČĎÉĚÍŇÓŘŠŤÚŮÝŽáčďéěíňóřšťúůýž. After pulling the latest commits, it would show that file as untracked, but adding and committing it would throw error: pathspec 'check in unicode fixture file once again' did not match any file(s) known to git.

Solution

Install Git version > 1.8.2 using homebrew and set

git config --global core.precomposeunicode true

Done.

Reason

According to the linked Stackoverflow post ...

... the cause is the different im...

How to mirror a git repo to a new remote

Say you want to move a git repository from one remote (perhaps Github) to another (perhaps Gitlab).

If you have the repo checked out, you still should make sure to mirror all branches of the old remote, not only those you happen to have checked our. Otherwise the target repo will become a copy of your current repo, and not the source repo, potentially missing commits. You can use this:

git remote rename origin old-origin
git remote add origin <new-remote>
git fetch old-origin --prune
git push --prune origin +refs/remotes/old-origin/*:r...

Git: How to check out branches that exist on multiple remotes

So you're using multiple remotes that offer the same branch?

$ git branch -a | grep my-branch
  remotes/something/my-branch
  remotes/origin/my-branch

And when trying to check out that remote branch, it fails for you with an error like this?

$ git checkout my-branch
error: pathspec 'my-branch' did not match any file(s) known to git.

Git usually guesses the remote branch to check out, but when using more than one remote, it seems like it no longer can do that.
Even if the branch is the same on both remotes, you nee...

Git: Delete a branch (local or remote)

To delete a local branch

git branch -d the_local_branch

To remove a remote branch (if you know what you are doing!)

git push origin :the_remote_branch

or simply use the new syntax (v1.7.0)

git push origin --delete the_remote_branch

Note

If you get the error

error: unable to push to unqualified destination: the_remote_branch
The destination refspec neither matches an existing ref on the remote nor
begins with refs/, and we are unable to guess a prefix based on the source ref.
error: failed to push some ref...

Git: How to show only filenames for a diff

When you want to do a git diff but do not care about the full diff and just want to know which files changed, use the --name-only switch:

$ git diff --name-only
app/controllers/sessions_controller.rb
app/models/user.rb
features/sign_in.feature

To include some brief information about changed lines, use the --stat switch:

$ git diff --stat
app/controllers/sessions_controller.rb |    8 +-
app/models/user.rb                     |   30 ++++
features/sign_in.feature               |  136 +++++++++++++++++

T...

Git: undo delete

Assuming you're wanting to undo the effects of git rm or rm followed by git add -A or something similar:

This restores the file status in the index:

git reset -- <file>

then check out a copy from the index

git checkout -- <file>

To undo git add , the first line above suffices, assuming you haven't committed yet.


Note:

Make sure to use double dashes -- to tell git to checkout a file instead of a branch. This only is relevant for [files having the same name as a branch](https://git-scm.com/docs/git-ch...

Git: "Interactive reverts"

If you need to revert only parts of one or several commits the following workflow can help:

If you need to revert multiple changes, make a branch and squash it afterwards.

For every commit you need to revert, starting at the most recent, do:

git revert -n [COMMIT] #revert, but don't automatically commit
... #fix any conflicts
git reset #unstage all changes
git add -p #this will ask you for every change, whethe...

Dropbox + git = Designer <3

One of the thornier problems in our workflow is knowing when assets are delivered from the designer and keeping them in sync with our application as they change. We used to use e-mail, Skype or sticky notes. The trouble is that the designer's file naming and directory structure were never quite the same as the application's /public/images directory, so direct comparisons were impossible and we ended with a lot bookkeeping to make sure that we didn't lose any changes. Our solution is to clone the project's git repository into a folder inside ...

Git: How to remove ignored files from your repository's directory

When you have files in your .gitignore they won't be considered for changes, but still you might want to get rid of them, e.g. because they clutter your file system.

While a regular git clean will ignore them as well, passing the -x switch changes that:

git clean -x

If you want to see what would happen first, make sure to pass the -n switch for a dry run:

git clean -xn

Clean even harder by passing the -f (force cleaning under certain circumstances; I think this is also required by default) or -d (removes director...

Git: Apply a diff

git apply allows you to apply a diff onto your HEAD. Most often you can achieve the same result with a rebase & merge.

Example:

master                commit1 - commit3
feature-branch                \ commit2 - commit4
git checkout feature-branch
git reset --hard commit3
git diff ..commit4 | git apply
master                commit1 - commit3
feature-branch                          \ Unstaged commit 2 & 4

You can also [create a patch and apply it afterwards](https://makandracards.com/makandra/2521-git-how-to...

How to ignore new files or changed files in git

How to ignore new files

Globally

Add the path(s) to your file(s) which you would like to ignore to your .gitignore file (and commit them). These file entries will also apply to others checking out the repo.

Locally

Add the path(s) to your file(s) which you would like to ignore to your .git/info/exclude file. These file entries will only apply to your local working copy.

How to ignore changed files (temporarily)

In order to ignore changed files to being listed...

Duplicate a git repository with all branches and tags

In order to clone a git repository including all branches and tags you need to use two parameters when cloning the old and pushing to the new repository respectively:

git clone --bare http://example.com/old-repo.git
cd old-repo
git push --mirror http://example.com/new-repo.git

Of course, the URLs to your repository might look different depending on the protocol used, username required, etc.
For a user git using the git protocol, it could be git@example.com:repository-namespace/repository.git

Git: How to automatically stage deleted files for commit

When you do a git add . and have deleted files, git won’t stage them to be commited (as deleted). Use

git add -u

From the git documentation: -u, --update <filepattern>

Only match against already tracked files in the index rather than the working tree. That means that it will never stage new files, but that it will stage modified new contents of tracked files and that it will remove files from the index if the corresponding files in the working tree have been removed.
If no is given, defa...

Git: Push a new branch and track it immediately

When you create a new branch and push it to origin, you won't be tracking it. This means a git pull won't know its remote version.

You could use difficult commands to set up a branch's tracking but it's easier to just push it like this:

git push -u

From the documentation on git push:

-u, --set-upstream
For every branch that is up to date or successfully pushed, add upstream (tracking) reference, used by argument-less git-pull(1) and other commands. For more information, see branch.<nam...

Git: Changing commit messages

To change the commit message of the latest (unpushed, unmerged) commit, you can use
git commit --amend

To change the commit message of an earlier (unpushed, unmerged) commit [COMMIT], you can do
git rebase -i COMMIT~

For a current version of git, you can simply mark the line with "reword", and git will ask you later for the new message.

For older versions:

  • mark the line with edit
  • save the file
  • do a git commit --amend when rebasing stops at the relevant commit
  • git rebase --continue

Git: Force a rejected push

If you modified git's history and the change was already pushed, you will usually get a
! [rejected] my-branch -> my-branch (non-fast-forward)
error, when trying to push.

You can force the push, with
git push --force origin my-branch

Careful:

  • You might lose history.
  • Unless your git is configured to push only the current branch, you must supply the remote branch name or you will force-push all your branches!
  • Anyone else who has already pulled the changes will run into significant trouble.

Only...

Prohibit Git from merging .po-files

Merging .po-files with Git is painful.

There have been attempts of making Git more clever when trying to merge .po-files. I believe however that this is not enough as it can still produce invalid .pos (usually due to double definitions), which can seriously confuse gettext afterwards.

Lacking any more secure solution, I think you should avoid editing po files in different branches at the same time. In order to not accidentally produce invalid merges I additionally ...

How to use Git on Windows with PuTTY

  1. Get "PuTTY Link" and "Pageant" (an SSH key agent) from the PuTTY download page.

  2. Run pageant.exe, find its icon inside your system tray and add your SSH key.

  3. Open up a cmd and put the full path to PuTTY's plink.exe into the GIT_SSH environment variable, e.g.:

    set GIT_SSH=D:\PuTTY\plink.exe
    

You can then use Git like you would on any sane operating system. Just go ahead and git clone, git pull, etc.

Also, you may want to add the environment vari...

Change commit messages of past Git commits

To change a commit message of the most recent (unpushed) commit, you can simply use
git commit --amend -m 'new message'

To change messages of (unpushed) commits further in the past:

git rebase -i [COMMIT BEFORE THE FIRST YOU WANT TO EDIT]

Mark all messages to be changed with "edit".

Git will start the rebasing and stop at every marked commit. For each of those, do a
git commit --amend -m 'new message'
git rebase --continue

Git: Remove information on branches that were deleted on origin

When branches get deleted on origin, your local repository won't take notice of that.

You'll still have your locally cached versions of those branches (which is actually good) but git branch -a will still list them as remote branches.

You can clean up that information locally like this:

git remote prune origin

Your local copies of deleted branches are not removed by this.

The same effect is achieved by using (kudos to Julien):

git fetch --prune

You could also set that as a default.

Git: Accessing lost commits

Every time you amend, rebase or reset, git commits get "overwritten".

However, git still allows you to checkout those commits using their SHA1, given you can find it.

One option to do this is

git reflog
# or
git reflog show [BRANCH]

This will show a list of all commits the branch has recently pointed to.

Git might garbage collect those commits eventually, but this should only happen after several weeks.

Git: Diff changes in a long line efficiently

Instead of showing you two lines for each change, Git allows you to highlight changes in a line explicitly:

git diff --word-diff some_file

Hello [-world-]{+universe+}!

(The result is usually colored nicely, the removed part being red and the added text green.)

When doing a diff on a long line, this can be very helpful but you'll still get a less-like scrolling output that can be unhandy to use.\
You maybe just want the diff put into your terminal:

PAGER='' git diff --word-diff some_file

Git: Define a custom merge driver

The ‘merge.*.driver` variable’s value is used to construct a command to run to merge ancestor’s version, current version and the other branches’ version. The merge driver is expected to leave the result of the merge in the file named with %A by overwriting it, and exit with zero status if it managed to merge them cleanly, or non-zero if there were conflicts.

Git instaweb

Git has a built-in repository viewer for your web browser. a bit similar (but less awesome) than github.

If you have apache installed, simply go to your repository, and enter
git instaweb --httpd apache2
otherwise, simply install lighttpd and just run
git instaweb

This should open a brower automatically pointing to your repository. If not, try to connect to localhost:1234.

You can stop the server with
git instaweb --stop