Git Combining Commit Not Pushed Yet

You are working on your computer, did several commit and you are ready to push. However, you may not want to push all the commit but only one that combine all your commit. Multiple cases exist like that you want all the code but not some of the comment related to commits. Another case could be that you the commit was not significant and you want to get ride of it. This is often the case of a commit without message. The change are required, but an empty commit is not.

To combine commit you need to use the rebase method inside your own branch. This is done by using rebase interactive command.

git rebase -i #All since the last commit
git rebase -i HEAD~5 #Last 5 commits

I wrote two commands that are doing almost the same. the first one does not specify the commit to takes. By default, it will takes all commit not pushed. The second command take the last 5 commits. This will redirect you to the interactive rebase screen. From that screen, it is possible to squash, edit or pick a command. You will also notice that the screen display all commit from the more old to the newest commit. You will see one line per commit. This allow you to edit every line by choosing if you want to keep the commit, with pick, to get the code but not the message with squash or to edit the commit with edit.

Let’s take the scenario that we want to combine everything in one commit. In that case, you pick the first commit ans squash all the other ones. You save and Git will open your default editor to allow you to edit the final message. Save and you are all set. At any time, if conflict occur you can abort. You just need to do the abort method of the git rebase command.

git rebase --abort

C# Allow External Library To Access Internal Visibility

I am not a fan of what I will show you here but it can be a life safer someday in your career. What I will show you is how to access an internal type from an external library. You have read it correctly. Even if the goal of internal visibility is to hide the type to be used outside the assembly, it is possible since framework 2.0 to create an exception by naming which assembly/library that can use the internal type.

Why would we want that? Well, a simple case could be that you want to unit test some internal classes and that you are doing all your unit test in a unit test project. This one needs to access the internal type and you must use a special attribute to allow that. Another case would be that you have the getter public but the setter internal. If you want a specify assembly to be able to write and no other one than you can use this attribute. This force you to have only one way to set information into your property.

The attribute is set anywhere in the code of your assembly. It can be at the top of a class or in AssemblyInfo file. Even if it is at the top of a class, remember that it allows to access the complete assembly. This is why it is a better approach to set the attribute in the AssemblyInfo file.

[assembly:InternalsVisibleTo("MyBusinessAssembly")]
[assembly:InternalsVisibleTo("MyOtherBusinessRelatedAssembly")]
[assembly:InternalsVisibleTo("MyUnitTestProjectName")]

If you are using signed DLL, than you will need to use the sn.exe command line tool. This one can be used directly in the Visual Studio Command Prompt. It will produce a public token that can be used in the InternalsVisibleTo attribute.

sn -Tp c:\yourpath\toyourdll\abc.dll
[assembly:InternalsVisibleTo("MyBusinessAssembly, PublicKey=00000000000111111111111122222222222.....")]
[assembly:InternalsVisibleTo("MyOtherBusinessRelatedAssembly, PublicKey=00000000000111111111111122222222222.....")]
[assembly:InternalsVisibleTo("MyUnitTestProjectName, PublicKey=00000000000111111111111122222222222.....")]

How To Use Git From Visual Studio Online

If you have a Git repository in Visual Studio Online and want to use a third party to manage your source code, like SourceTree, you need to configure something in Visual Studio.

First, open your Visual Studio Online portal and go into your profile to setup an alternative authentication. The profile is in the top-right corner of Visual Studio. Click your name and then click My Profile.

Step1Profile

Second, click the Crendential tab. This will allow you to have an alternative login name and a password to use for application like SourceTree (or any other system).

Step2AlternateAuthentification

When this is done, the third step is to copy the Git Http path which is the one you see in your browser when you click in the project you want to code, then code. The syntax should looks like the example below.

https://YOURRepositoryNAME.visualstudio.com/DefaultCollection/_git/Project

You need that http url to paste it into your software and be able to clone the repository. From there, you can use git to do every other commands you wish.

System.IO.Path.GetFullPath

You manipulate paths and files with System.IO.Path which is better than trying to handle everything by string. Great! You are using Path.Combine(“c:\data\”,”file.txt”) everything is fine. You have understand that combining path and file are way easier with Path.Combine. It handles for you every slashes, so you do not have to handle string with substring and indexof. However, the dream stop brutally the day you have something with relative path that goes to parent folder. For example, the example below crash.

Path.Combine("c:\data\","..\file.txt")

Having double dot return the the c: drive in the example above, but combine will not do it for you. THis is why you need to use Path.GetFullPath.

Path.GetFullPath("c:\data\..\file.txt")

This will clean the path and output c:\file.txt.

The conclusion is that file path manipulation must still use the System.IO.Path but different methods should be used depending of the case you are encountering.

Create a New Git Branch with Uncommited Code

If you started doing some code modification but you realize that you should have done these modifications in a branch instead of directly into the branch you did the modification, you can move all files into a new branch. The command is checkout with the parameter -b which create the branch if this one does not exist.

git checkout -b NewBranch
git add .

The git add . simply add all uncommited file into the staged area.

Other possibility exist like using git stash to move uncommited code into a temporary place and unstash into another branch.

git stash
git checkout NewBranch
git stash apply

Git Adding a File to a Previous Commit

Imagine that you are doing a commit and you forgot to bring a file or multiples files. You can do a second commit but this would have the consequence to have two commits for something that in fact would have been in one. Git allows you to alter a past commit with the amend parameter.

For example, here is a small commit of 1 file.

git add main.cs
git commit -m "This is my first commit"

This is how to add a second file to this first commit.

git add util.cs
git commit --amend --no-edit

The –no-edit parameter specify that we do not want to modify the message. If you are doing a git log, you will see a single commit.

How to Rebase your Working Branch Without Commit your Working Files

Let’s start by building the scenario that you have two files that you want to share to everybody and one that is a configuration file that should not be shared. In some point in the development you want to get the latest version of the master branch into your feature branch. This require to you to do a merge or to rebase. Merging is interesting but will cause having in your feature branch all file becoming modified which will be hard later for the pull request. The reason is that you want to pull request only your modification and not the files that has been merged. This is where rebase can be interesting. The problem is that if you try to rebase you will get a message saying that you need to commit or stash or change first. This is comprehensive since when rebase you are moving the HEAD of your feature branch in the front of the master one. It needs to have a “node” to move. To do, you have to go into your feature branch, add all files you want to commit and commit.

git checkout Feature1
git add File1
git add File2
git rebase master

The last line will fail. The reason is that you still have the configuration file not commited, and you do not want to. This is where the stash command shine. The git stash command allow you to put somewhere the remaining files that have change into a “stash” which will allow you later to get back (after the rebase). To execute the stash, you have to execute the stash command in the branch you want the files not staged to be stashed.

git checkout Feature1
git stash
git rebase master
git stash pop

You should be all set with the latest version of the master branch and also your files back (the configuration file in our example).

GitHub Command Line Basic

The first thing is to create a repository. You can create one free at GitHub. After created the repository on GitHub get the URL of the repository and copy paste to the console with the clone command.
GitHubCloneHttpUrl

Download the repository to your computer with the clone command.

git clone https://github.com/MrDesjardins/TestingGit.git

GitCloneExistingRepository
Open notepad and modify an existing file. You can do it manually by specifying the file

git add README.md

You can use the add command with the the -u for all modified file but not for adding new file.

In both case, if you check the status you will see that the file is modified.

git status
git commit -m "Message here"
git status

Checking the status will not any more say that the file is modified but that your branch is ahead of origin/master by one commit

Doing another change on the same file will set back the status to modified.

You need to commit again before sending everything to the server. If you do not want to have the latest change, before commiting you can rollback the file with the checkout command.

git checkout readme.md

Before having your code available with everybody, it is possible to see all branches.

git branch -r 
git branch -a

To send the code to the server, we need to push. We need to specify the the remote.
git push origin master

This was the easy step. Now let’s dp a branch that we will than later merge back into this master branch.

git checkout -b "Branch1"
//or
$ git branch Branch1
$ git checkout Branch1

if we are checking the branches, we will see one local branch and not a remote one.

git branch -a
//create file test1.txt
git add text1.txt
git commit -m "Added test1.txt from branch1"
git checkout -b Branch2
//create file test1.txt
git add text1.txt
git commit -m "Added test1.txt from branch2"

From there we can do several thing like a pull request, pulling directly or pushing to another branch.
Let’s first stats with a pull request. To do, you need to go on Github.
GitComment

The web UI allows you to comment on the branch, but also inside every files. At the end, we can close the pull request.

You can close the pull request if you are not satisfy or you can accept and merge form the website or the console.
The console allows you to get the code and test it before pushing it back to the server. If you do not have the branch on your computer than you need to fetch and checkout. Finally, merge the master to the branch to check the pull request with the whole main branch.

git fetch origin
git checkout -b branch1 origin/branch1
git merge master

Once everything is done (mergin, making sure that it build, unit test works, etc), than it is the time to merge everything in the master.
or if you already have the branch in your computer, you can get the code with the fetch command and than check the modification with git log. Finally, you can get merge.

git fetch origin origin/branch1
git log origin/branch1
git merge origin/branch1

To accept the pull request this can be done by checkout the master and merge the branch into it. Finally, push everything to the server.

git checkout master
git merge --no-ff branch1
git commit -m "Merging Blah Blah"
git push origin master

Like in this example, conflict can occur.
GitConflct
You can also see the conflict with the git status command.
GitStatusConflict

Before resolving conflict, you need to be sure that you have configured the merging tool. Here is the configuration for WinMerge. This configuration must be set in your .gitconfig from your user folder. You can access it by using : %USERPROFILE%/.gitconfig

[merge]
    tool = winmerge
[mergetool "winmerge"]
    cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" -e "$MERGED"
    keepBackup = false
    trustExitCode = false

    tool = winmerge
[difftool "winmerge"]
    cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" -e "$LOCAL" "$REMOTE" -dl "Local" -dr

If you prefer kdiff3 tool which is a 3-way commit tool use this command

[merge]
    tool = kdiff3
[mergetool "kdiff3"]
    path = C:\\Program Files (x86)\\KDiff3\\kdiff3.exe
    keepBackup = false
    trustExitCode = false

From there you can go git mergetool and git will go through all files that must resolve conflict.

git mergetool

Once all conflicts solve, merge done, commit done and push to the server done, than the pull request is automatically closed for you.

We still have branch 2 to merge. Let’s do it without pull request. But before, lets move into branch2 and delete the readme file. Than let’s try to undo this delete.

git checkout branch2
del readme.md
git checkout -- readme.md

Same thing with a new file.

git add readme.md2
git reset readme.md2

Last thing with a modified date.

//modify file
git checkout -- readme.md

So you have two remembers two different commands. One is checkout and one is reset to undo something to a file.

Concerning undoing, if you have commit, you can also undo this command. In fact, committing only put the file in the stage area. To undo a commit use the git reset command.

git reset --soft HEAD~1