Adrian Andreias

Sep 24, 2014

Fresh git tips

1. Pull all branches without merge commit

git pull --ff-only --all

Pulls all branches from remote and merges only if there are fast-forward changes (that don't require a merge), otherwise fails. If any of the pulls fails you can handle it individually - you need to do that anyway.

Unfortunately git pull --all only does fetch --all and not the merging part on all branches, but only on current branch. There's git-up, but I don't like the automatic rebasing part. I'll keep searching for a solution that fits my needs. A little bash script in .gitconfig alises would be probably easiest.

2. Colored log tree view

git log --oneline --all --graph --decorate --color

3. And alias'em: `git pa` and `git lg`

Edit your user's git config \~/.gitconfig to create shortcuts for the two git commands:

[alias] lg = log --oneline --all --graph --decorate --color pa = pull --ff-only --all

Sep 01, 2014

Git cancel pull merge and overwrite local files

I'm usually writing code on two machines: the Intel NUC running Arch Linux at the office and the Windows 8.1 HP Ultrabook at home (the Microsoft Office package keeps me on Windows. I tried Evolution with the Exchange plugin a few days ago on my Arch Linux and it was stalling the machine with my 5GB of mail and I had to cold reboot a few times a day). Good thing PyCharm allows me to use my license on multiple machines.

I have a personal repository on our Gitlab server and I use it to copy code from one machine to another:

  1. I'm amending the last commit and push it to server from the machine I've last used:
git add . git commit --amend --no-edit git pus
  1. On the second machine I usually just pull:
git pull

This might cause a merge conflict if I happen to have some small and unimportant changes on the second machine. This will always cause a conflict when you're actually overwriting the local history. If I am sure that I can dump the changes on the local machine I can force the pull to overwrote local changes:

# cancel the current merge that was initiated by git pull:
git reset --hard HEAD
# not normally needed since git pull already fetched:
git fetch --all
# use remote code and overwrite local code:
git reset --hard origin

And this little article should save me the googling I do each time I do a git pull. :)

Jul 21, 2014

Merge git personal/master to upstream/master

So you forked the project's repo to your own personal remote repo (in Gitlab/Github/etc.) and you committed your changes to personal/master and now you're trying to merge your commits to upstream/master. (Good idea to work in a branch, and not on master, by the way :)

You'll have a problem because both branches, from the personal and the upstream repos, are called master.

I gave up doing this when working with a single local git directory that has the origin/master branch tracking the personal remote repo and upstream/master branch tracking the main repo because would involve some non-straight forward configs that look hard to debug/maintain.

Another option is to do the merge in another directory. You'd have a separate local repo (besides the personal development repo) that is cloned from the upstream:

git clone git@gitserver:<<theproject>>/<<theproject>>.git .

and:

# add your personal (development) remote repository
git remote add <<adrian>> git@gitserver:<<adrian>>/<<theproject>>.git .
# create a local branch named <<adrian>>-master (avoiding the master name collision!) tracking <<adrian>>/master
git fetch <<adrian>> git checkout -b <<adrian>>-master <<adrian>>/master
# make sure you're on origin/master (main/upstream project)
git checkout master
# and merge your commits into main project
git merge <<adrian>>-master --ff-only
# send the commits to main project remote server
git push

Notes:

  • I'm using Gitlab 7.0, but that should matter (it uses the git ssh user for key based authentication). I'm doing the merge from command line because I want to have fast-forward merges (without an extra commit for the merge - this is how the pull request merge works in the Gitlab web interface). Also, my pull request web page is crashing right now, but that's another story.
  • replace <<adrian>> with your personal repo name
  • same with <<theproject>>
  • gitserver is obviously your own git server hostname

Jul 17, 2014

More git trickery

Difference between working directory/stage/HEAD

git diff

Shows the changes between the working directory and the index. This shows what has been changed, but is not staged for a commit.

git diff --cached

Shows the changes between the index and the HEAD (which is the last commit on this branch). This shows what has been added to the index and staged for a commit.

git diff HEAD

Shows all the changes between the working directory and HEAD (which includes changes in the index). This shows all the changes since the last commit, whether or not they have been staged for commit or not.

Modify commit history: edit/split/merge commits

Do not modify commits that have already been pushed! Unimaginable nasty things can happen!

There is a guide to splitting commits in the rebase manual. The quick summary is:

  • Perform an interactive rebase including the target commit (e.g. git rebase -i "<commit-to-split>^" branch) and mark it to be edited. Note that double quotes are required in Windows, otherwise the caret symbol will be interpreted by cmd.exe by escaping the following character. You can also specify the commit before the one you want to edit, this time without the caret: git rebase -i <the-commit-before> branch
  • When the rebase reaches that commit, use git reset "HEAD^" to reset to before the commit, but keep your work tree intact.
  • Incrementally add changes and commit them, making as many commits as desired. add -p can be useful to add only some of the changes in a given file. Use commit -c ORIG_HEAD if you want to re-use the original commit message for a certain commit.
  • You can also git commit --amend in order to modify a commit, otherwise new commits will be created.
  • If you want to test what you're committing (good idea!) use git stash to hide away the part you haven't committed (or stash --keep-index before you even commit it), test, then git stash pop to return the rest to the work tree. Keep making commits until you get all modifications committed, i.e. have a clean work tree.
  • You can also abort your rebase if you messed things up completely: git rebase --abort
  • Run git rebase --continue to proceed applying the commits after the now-split commit.

Based on: http://stackoverflow.com/a/4307158

Restoring lost commits

Assuming you ran git reset --hard HEAD^ or just messed with rebasing causing you to lose a commit or more. Don't panic. Git should still have your commits in the data store until the next garbage collection cleans it up, unless you ran git gc.

So your commit(s) doesn't show up when you run git log, you should see them when running git flog. Identify in the flog the commit you want to switch to and run:

git merge <commit-hash>

Show file at specified revision

git show 2c624a9:a.txt git show HEAD~3:a.txt git show "HEAD^":a.txt

Jan 22, 2013

git your home dir

Having all sorts of .vimrc, /.vim (like .sls files syntax), /.gitconfig settings in my Linux home dir made want to easy port this between servers. So I initialized and pushed to server a git repository and wanted to pull files from git on another server:

cd ~
git clone ssh://<git user>@<git server>/<repo path> .
fatal: destination path '.' already exists and is not an empty directory.

So, we need to get a git repo to a non-empty directory. Stackoverflow comes in handy (as most of the time) and tells us to:

cd ~
git init
git remote add origin ssh://host/repo.git
git pull origin master
posted at 17:53 ·  · git

Jan 18, 2013

my git reminder

(to be updated)

1. Create the local git repository

Even if you don't plan to use a git server and only store files on your localhost you should create a git repository as early as possible because:

  • you will have a file editing history, provided that you'll commit frequently
  • it only takes a few seconds to create a git repo

(Note that "git commit" means something slightly different than "svn commit". Since svn always assumes having a svn server, git can be used just on your local file system, a git server is not mandatory. Git will keep track of your changes in his internal database stored in directory .git by default. git push would be the equivalent of svn commit, that is publishing changes to a server).

Without further ado:

  1. git init # this will create the git database under directory .git from current path
  2. create file .gitignore. This contains the list of files that will not be added to git database. Here's what mine usually contains: .idea *.pyc settings.py
  3. git add * # to add all files
  4. git commit -a # to commit all files

Read more in the git book.

And GIT for SVN users:

2. Initial server push

Once you have the local git repository you'll want to publish to the git server.

  1. Create the repository on your git server:

    cd /var/repos mkdir myproject.git cd myproject.git git init --bare
    
  2. Add remote server:

    sudo git remote add origin
    ssh://<git user>@<git server>/var/repos/myproject.git
    
  3. and push your local repository to remote server:

    sudo git push -u origin master
    

Inspiration:

posted at 10:44 ·  · git