Just two months after version 2.6, Git 2.7 was released with new features, fixes and performance improvements. What interesting things did he cook for us? I will talk about several new products that seemed interesting to the Bitbucket team.
Full git worktree command set
The 
git worktree command appeared in Git 2.5 , it allows you to upload and simultaneously work with many branches of the repository in 
separate folders. For example, if you need to make an urgent revision, but you do not want to touch the current working copy, you can simply unload the necessary branch into a 
new folder using the command:
$ git worktree add -b hotfix/BB-1234 ../hotfix/BB-1234 Preparing ../hotfix/BB-1234 (identifier BB-1234) HEAD is now at 886e0ba Merged in bedwards/BB-13430-api-merge-pr (pull request  
Git 2.7 adds the 
git worktree list command , which lists the working copies of the repository and the branches associated with them:
 $ git worktree list /Users/kannonboy/src/bitbucket/bitbucket 37732bd [master] /Users/kannonboy/src/bitbucket/staging d5924bc [staging] /Users/kannonboy/src/bitbucket/hotfix/BB-1234 37732bd [hotfix/BB-1234] 
Improved support for many working copies with the 
git bisect command. The links that were used by the 
bisect for “good” and “bad” commits moved from 
.git / refs / bisect to 
.git / refs / worktrees / $ worktree_name / refs / bisect , so now the 
bisect can work in different working copies of the repository .
In addition, starting with Git 2.7, you can use 
git clone , specifying such a separate working copy as an argument - this will create an independent git-repository, and not another working copy of the existing one.
')
It is noteworthy that separate working copies can be created not only for branches. Like many other commands, 
git worktree add can be called with a pointer to a commit, be it its hash or tag:
 $ git worktree add ../git-2.4.7 ca00f80 Preparing ../git-2.4.7 (identifier git-2.4.7) HEAD is now at ca00f80 Git 2.4.7 $ git worktree add ../git-v2.6.0 v2.6.0 Preparing ../git-v2.6.0 (identifier git-v2.6.0) HEAD is now at be08dee Git 2.6 $ git worktree add ../git-v2.7.0 v2.7.0 Preparing ../git-v2.7.0 (identifier git-v2.7.0) HEAD is now at 7548842 Git 2.7 $ git worktree list /Users/kannonboy/src/git 7548842 [master] /Users/kannonboy/src/git-2.4.7 ca00f80 (detached HEAD) /Users/kannonboy/src/git-v2.6.0 be08dee (detached HEAD) /Users/kannonboy/src/git-v2.7.0 7548842 (detached HEAD) 
Some git stash improvements
If you are a fan of 
git rebase , then you are most likely familiar with the 
--autostash option. It automatically saves all local changes to temporary storage ( 
stash ) before 
rebase , and after its completion applies them again.
 $ git rebase master --autostash Created autostash: 54f212a HEAD is now at 8303dca It's a kludge, but put the tuple from the database in the cache. First, rewinding head to replay your work on top of it... Applied autostash. 
This is convenient because you can 
rebase on a dirty working copy. For even more convenience, there is the 
rebase.autostash option , which makes this described as the default behavior. Apply it globally using the command:
 $ git config --global rebase.autostash true 
This parameter 
still exists with Git 1.8.4 , but the ability to cancel it with the option 
--no-autostash has been added to Git 2.7. Most likely, this option is added for completeness, since the only thing it gives when trying to 
rebase on a dirty working copy is the corresponding warning:
 $ git rebase master --no-autostash Cannot rebase: You have unstaged changes. Please commit or stash them. 
Speaking of configuration, it is also worth mentioning the 
stash.showPatch parameter, which also appeared in Git 2.7. At standard settings, the 
git stash show command displays only brief information about the files in the temporary storage:
 $ git stash show package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 
If you additionally specify the 
-p option, the output will be supplemented with an extended description of file changes:
 diff --git a/package.json b/package.json index c876b26..e21eeb3 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "mkdirp": "^0.5.0", "byline": "^4.2.1", "express": "~3.3.4", - "git-guilt": "^0.1.0", + "git-guilt": "^0.1.1", "jsonfile": "^2.0.0", "jugglingdb-sqlite3": "0.0.5", "jugglingdb-postgres": "~0.1.0", 
The 
stash.showPatch parameter makes this the default behavior. Apply it globally using a similar command:
 $ git config --global stash.showPatch true 
As in the previous case, the included parameter can be canceled and thus return to the old brief output - using the option 
--stat :
 $ git stash show --stat package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 
Be careful: the option 
--no-patch does not cause an error, but it does not cancel the 
stash.showPatch , as you would expect.
Acceleration git filter-branch and progress indicator
git filter-branch is a universal tool for changing the repository history. Since each commit has references to parent commits, which means it transitively refers to all commits that are its ancestors, changing one commit inevitably entails changing all its descendants. This, in turn, means that an operation of even an elementary change in history can take some time, if you need to change a rather old commit.
In Git 2.7, an elegant progress indicator appeared that displays the estimated time until the end of the 
filter-branch run:

In addition, if 
filter-branch does not change objects in the index or trees, then the index is not read at all when the command is executed, which significantly increases its performance. The 
--commit-filter option on the animation above changes only the author of each commit and does not affect the tree objects associated with them. Changing the first 1000 commits of 
Bitbucket Server took only 38 seconds using Git 2.7.0, while a similar operation with Git 2.6.0 took 64 seconds, that is, the speed increase was as much as 
40% . Performance tests, introduced in Git 2.7 with these improvements, show an 
even more impressive acceleration - up to 
60% .
Improved Negation in .gitignore
The 
.gitignore files 
allow you to exclude some files in the working copy from the repository, i.e. they will not be added to the index. Patterns support the negation flag with the prefix 
! so that it is possible to cancel the ignoring of a specific file. For example, with such templates, git will ignore all files with a 
.json extension, except 
cat.json :
  
However, in Git 2.6 it was impossible to apply a negative to a file that is already in the ignored folder.
  
Starting from Git 2.7, the second example works exactly as expected: with 
! Now you can cancel ignoring files in folders that would otherwise be ignored.
But that's not all!
This is only a small part of the buns that appeared in Git 2.7. The full list of changes can be found in 
the release notes , as well as in the comments to the commits in 
the Git repository itself :
 $ git log v2.6.0..v2.7.0 
The author of the 
original article , Tim Pettersen, participated in the development of JIRA, FishEye / Crucible and Stash. From the beginning of 2013, he talks about development processes, git, continuous integration and continuous integration / deployment, and Atlassian tools for developers, especially Bitbucket. Tim regularly posts notes about these and other things on Twitter under the pseudonym 
@kannonboy .