Monday, January 19, 2015

Git Workflow

Workflow
git status
new files will be listed as "Untracked files:" and use git add to put them into the repo as staged
git add *   (stages all, seems to do the same as git add --all)
git add .  (stages new and modified without deleted files)
git add -u  (stages deleted and modified without new files)
git add .\folder\filename.txt
git commit -m "message"
commit to remote repo
git push origin <branch>
git push -u origin <branch>    (push new local branch not yet on remote. -u short for --set-upstream)

Merge branch to master:
git checkout master
git pull origin master
git merge <branch>
git push origin master
git branch -d mybranch    (deletes mybranch locally only)
git push origin -d mybranch    (deletes remote mybranch)

git fetch origin  (makes the local tracking branch up to date of the current branch, does NOT modify working directory)
git merge origin/master

git checkout dev  (DWIM version that will create a local branch dev and if dev exists on remote it will set up a tracking branch for it.)

Push to master
git push origin master

Diff
git difftool .\folder\Web.config      (compares local to remote, you may not need the leading .\)
git difftool --dir-diff .\SportsStore\SportsStore  (all changes in this and subfolders, except deletes I think)
git difftool --dir-diff master origin/master  (Will not do anything including not launching diff UI if local matches remote)
git difftool d60f4cf..8d6e908 compares commits. If > 1 file is in the result, you will be prompted, so escape out of compare tool to get to the next file. A caret ^ before the .. (git difftool d60f4cf^..8d6e908) has a different behavior, not sure what that is.

Log
git log --oneline       (git logsimp using alias)
git log --oneline ./src/main/mule/training4-american2-ws.xml

this is the same as git logSimp   (using alias):
        git log --pretty=format:"%h - %an: %s" --shortstat
git logsimp -5     (returns the last 5 log entries)

Log using aliases:
git logsimp
git logsimpfiles
git logsimpdates
git logsSmpAge


History of a file (last 5 checkins)
git lsf -5 .\SportsStore\SportsStore.Tests\IocTests.cs
Now you can view the diff by changeset
git dcd f028a41
 
Aliases
git list-aliases (this is an alias...)

Branching and Working with Branches
git branch (shows local branches)
git branch -r (remote tracking branches)
git branch -a (remote and local branches)
git branch -vv (lists local branches and their mapped remote tracking branch. If working directory is ahead 3 checkins then it will say that next to the remote branch, and after the remote branch's closing bracket ] it will show the last checkin message from the remote server. All info is based on last fetch from server.)
git show-branch --all  (shows any checkins that are ahead of remote, then the remote branch)
git branch -d mybranch    (deletes mybranch locally only)

git push origin -d mybranch    (deletes remote mybranch)
git push -u origin <branch>    (push new local branch not yet on remote. -u short for --set-upstream)

Create a new branch from master
Get local in sync with remote.
git branch dev (does not create a corresponding remote tracking branch, which means another developer won't see it and you can't push to remote using git push --all when in dev branch.)
Then do:
git push -u origin dev. Now other developers will be able to do a git fetch origin and then git checkout dev and see the changes you made in dev branch.

Switching to other branch(es)
If you make a change in master w/out staging it or checking it in and you do a checkout to dev branch, one of 2 things can happen:
1) You will get an error message saying you might lose your changes in master.
2) You will be checked out to dev but the dirty files will now be in the dev branch.
Scenario 2 seems dangerous and I don't know why git doesn't consistently throw an error. Seems a bad choice to just allow those changes into the other branch's working directory.

If I have unstaged or staged files in master and I want to switch to dev without checking in to HEAD my changes in master, I can do:
git stash -u   (stashes unstaged files in working dir)
and now you can do
git co dev  and you'll be good

** caution - doing a stash, then making more changes and doing yet another stash so you have 2 stashes when you do a list can cause problems when you go to pop the second time. You may get a merge error. So don't stash more than once. (well, sort of, I got the error, then did a drop and the untracked file in the first stash got restored. KISS, only one stash.)

git stash pop  (takes latest stash, stash@{0} and restores it. Do it again and it restores the next in the stack)
git stash apply  (caution, I think the stash may persist...)
git stash list   (to see what you have stashed)
git stash drop  (deletes the stash at the top of the stack and you lose those changes, sort of, see caution above.)



Fetching/Merging
if a branch "serverfix" was created by a co-worker and he pushes it onto the server, and you do a [git fetch origin], this fetch creates a reference (this is a remote-tracking branch) to where the serverfix branch is: origin/serverfix. This does not bring any files down that you can work on, you have to do a checkout for that. So at this point, without doing a checkout yet, with the fetch we've only created locally a remote tracking branch for serverfix.
So it's like the relationship I got after doing my clone with master and origin/master. The clone, however did bring files down and at the same time created the remote tracking branch.
git checkout -b serverfix origin/serverfix
-- this will download files from server (origin) and switch (don't know how switch works) to the new branch serverfix. I hope that a new folder is created. I'm sure it does, the "switch" means that git now is in the context of serverfix, not master on the local machine. So if I work on files on my file system that map to master, then (I think) my powershell will not track any work I do there, it is only looking at serverfix changes.
So what the above checkout command does is "checks out a local branch from a remote-tracking branch"

Move to new folder
I had a VS solution that was in c:\TestGit\TestBootstrap\TestBootstrap
This folder had the root of the solution (however the .sln file was in c:\TestGit\TestBootstrap
I wanted to have the new folder structure be c:\TestGit\TestBootstrap\trunk\src
So I added to my local the trunk and src folders with a temp file in there so it would actually get into git.

do a 'git add *' (puts the folders into git staging)

do a 'git mv -n' first for a preview

git mv  -n TestBootstrap/TestBootstrap TestBootstrap/trunk/src
The above command worked from repo root of c:\TestGit.

Don't forget to delete the temp file.

Links

Test/learning scenarios
================
Scenario - Check-in Dance:
Branch master is like trunk, we don't work there, we merge changes from dev branch mainly. This scenario says do some work in dev, check it into remote, then merge it to master. Then have co-worker download changes in both.
git fetch origin
git merge origin/<branch>
co-worker does same

Scenario - Undoing:
Revert all local uncommitted changes (should be executed in repo root):
git checkout .

Unstage all files you might have staged with git add:
git reset

Revert uncommitted changes only to particular file or directory:
git checkout [some_dir|file.txt]

Yet another way to revert all uncommitted changes (longer to type, but works from any subdirectory):
git reset --hard HEAD

Undo working directory changes (unstaged changes):
git checkout -- . (replaces working directory with what is in index. Will restore deletes.)
Caution, stashing doesn't play nice with deleted files.
git stash -u  (understand what stash does before using)
git stash


Scenario - Merge master to dev: Change made in master branch after dev branch was created from master. All changes in both branches are pushed to remote repo. This scenario says we should only work from dev branch, so we need to now merge master up to dev.
~merge master into dev~ dev
git checkout dev
git merge master

Scenario - Conflicts: Two coworkers are totally in sync with remote and have not yet made any changes. Then they both change the same line on the same file and check in and push to master. What happens? How do you resolve this?
So coworker A pushes his change to remote successfully. B commits his but when attempting to push to origin gets an error and it won't let him. So B has to do a fetch and merge and git will tell him there is a conflict and he'll have to resolve it. Whatever the resolution the next step for B is to push to origin and then A can do a fetch/merge.
** But alas, we must always do the check-in dance -- first do a fetch and merge, and deal with the conflict locally.

Scenario - Working in Wrong Branch: I thought I was working in dev branch but instead I was in master and made enough changes to not want to lose them or to manually move them.
So basically, I want to move changes in my master branch working directory to the dev branch working directory.
  • So we are in master branch.
  • git stash list (make sure there aren't any other stashes, or of so, keep track so you know what's what)
  • git stash -u (see above)
  • git stash list (see the new stash
  • git co dev
  • git stash list
  • git stash pop (now those changes get applied to dev)
Scenario - Add your code to a new repository: I created a new BitBucket repo, then I created a new VStudio or Android project, now I want to add the project into the new remote repo.
 
(see below if you are doing something like cloning from someone else's GitHub, then wanting to add it to a new BitBucket repo)
  • There is a link on BitBucket's repo page to do this just after you create the repo in BB: "I starting from scratch " (something like that)
  • Navigate console to root of project on local machine
  • git init
  • git remote add origin https://ttonnesen@bitbucket.org/ttonnesen/maplauncher-web.git
  • git add --all
  • git ci -m "initial checkin"
  • git push origin master
From GitHub to BitBucket:
  • Delete the git files from the root of the project (except for maybe the gitignore)
  • You are going to do a git clone of your new BitBucket repo, so it will download a folder and inside that folder will be the git files, so the repo will be inside that folder, so decide where that downloaded file will live. You can always move it after you do the clone.
  • Now throw the files you cloned from GitHub into that new folder you cloned down from BitBucket.
  • git add --all
  • git ci -m "initial checkin"
  • git push origin master




No comments:

Post a Comment